1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92: 93: 94: 95: 96: 97: 98: 99: 100: 101: 102: 103: 104: 105: 106: 107: 108: 109: 110: 111: 112: 113: 114: 115: 116: 117: 118: 119: 120: 121: 122: 123: 124: 125: 126: 127: 128: 129: 130: 131: 132: 133: 134: 135: 136: 137: 138: 139: 140: 141: 142: 143: 144: 145: 146: 147: 148: 149: 150: 151: 152: 153: 154: 155: 156: 157: 158: 159: 160: 161: 162: 163: 164: 165: 166: 167: 168: 169: 170: 171: 172: 173: 174: 175: 176: 177: 178: 179: 180: 181: 182: 183: 184: 185: 186: 187: 188: 189: 190: 191: 192: 193: 194: 195: 196: 197: 198: 199: 200: 201: 202: 203: 204: 205: 206: 207: 208: 209: 210: 211: 212: 213: 214: 215: 216: 217: 218: 219: 220: 221: 222: 223: 224: 225: 226: 227: 228: 229: 230: 231: 232: 233: 234: 235: 236: 237: 238: 239: 240: 241: 242: 243: 244: 245: 246: 247: 248: 249: 250: 251: 252: 253: 254: 255: 256: 257: 258: 259: 260: 261: 262: 263: 264: 265: 266: 267: 268: 269: 270: 271: 272: 273: 274: 275: 276: 277: 278: 279: 280: 281: 282: 283: 284: 285: 286: 287: 288: 289: 290: 291: 292: 293: 294: 295: 296: 297: 298: 299: 300: 301: 302: 303: 304: 305: 306: 307: 308: 309: 310: 311: 312: 313: 314: 315: 316: 317: 318: 319: 320: 321: 322: 323: 324: 325: 326: 327: 328: 329: 330: 331: 332: 333: 334: 335: 336: 337: 338: 339: 340: 341: 342: 343: 344: 345: 346: 347: 348: 349: 350: 351: 352: 353: 354: 355: 356: 357: 358: 359: 360: 361: 362: 363: 364: 365: 366: 367: 368: 369: 370: 371: 372: 373: 374: 375: 376: 377: 378: 379: 380: 381: 382: 383: 384: 385: 386: 387: 388: 389: 390: 391: 392: 393: 394: 395: 396: 397: 398: 399: 400: 401: 402: 403: 404: 405: 406: 407: 408: 409: 410: 411: 412: 413: 414: 415: 416: 417: 418: 419: 420: 421: 422: 423: 424: 425: 426: 427: 428: 429: 430: 431: 432: 433: 434: 435: 436: 437: 438: 439: 440: 441: 442: 443: 444: 445: 446: 447: 448: 449: 450: 451: 452: 453: 454: 455: 456: 457: 458: 459: 460: 461: 462: 463: 464: 465: 466: 467: 468: 469: 470: 471: 472: 473: 474: 475: 476: 477: 478: 479: 480: 481: 482: 483: 484: 485: 486: 487: 488: 489: 490: 491: 492: 493: 494: 495: 496: 497: 498: 499: 500: 501: 502: 503: 504: 505: 506: 507: 508: 509: 510: 511: 512: 513: 514: 515: 516: 517: 518: 519: 520: 521: 522: 523: 524: 525: 526: 527: 528: 529: 530: 531: 532: 533: 534: 535: 536: 537: 538: 539: 540: 541: 542: 543: 544: 545: 546: 547: 548: 549: 550: 551: 552: 553: 554: 555: 556: 557: 558: 559: 560: 561: 562: 563: 564: 565: 566: 567: 568: 569: 570: 571: 572: 573: 574: 575: 576: 577: 578: 579: 580: 581: 582: 583: 584: 585: 586: 587: 588: 589: 590: 591: 592: 593: 594: 595: 596: 597: 598: 599: 600: 601: 602: 603: 604: 605: 606: 607: 608: 609: 610: 611: 612: 613: 614: 615: 616: 617: 618: 619: 620: 621: 622: 623: 624: 625: 626: 627: 628: 629: 630: 631: 632: 633: 634: 635: 636: 637: 638: 639: 640: 641: 642: 643: 644: 645: 646: 647: 648: 649: 650: 651: 652: 653: 654: 655: 656: 657: 658: 659: 660: 661: 662: 663: 664: 665: 666: 667: 668: 669: 670: 671: 672: 673: 674: 675: 676: 677: 678: 679: 680: 681: 682: 683: 684: 685: 686: 687: 688: 689: 690: 691: 692: 693: 694: 695: 696: 697: 698: 699: 700: 701: 702: 703: 704: 705: 706: 707: 708: 709: 710: 711: 712: 713: 714: 715: 716: 717: 718: 719: 720: 721: 722: 723: 724: 725: 726: 727: 728: 729: 730: 731: 732: 733: 734: 735: 736: 737: 738: 739: 740: 741: 742: 743: 744: 745: 746: 747: 748: 749: 750: 751: 752: 753: 754: 755: 756: 757: 758: 759: 760: 761: 762: 763: 764: 765: 766: 767: 768: 769: 770: 771: 772: 773: 774: 775: 776: 777: 778: 779: 780: 781: 782: 783: 784: 785: 786: 787: 788: 789: 790: 791: 792: 793: 794: 795: 796: 797: 798: 799: 800: 801: 802: 803: 804: 805: 806: 807: 808: 809: 810: 811: 812: 813: 814: 815: 816: 817: 818: 819: 820: 821: 822: 823: 824: 825: 826: 827: 828: 829: 830: 831: 832: 833: 834: 835: 836: 837: 838: 839: 840: 841: 842: 843: 844: 845: 846: 847: 848: 849: 850: 851: 852: 853: 854: 855: 856: 857: 858: 859: 860: 861: 862: 863: 864: 865: 866: 867: 868: 869: 870: 871: 872: 873: 874: 875: 876: 877: 878: 879: 880: 881: 882: 883: 884: 885: 886: 887: 888: 889: 890: 891: 892: 893: 894: 895: 896: 897: 898: 899: 900: 901: 902: 903: 904: 905: 906: 907: 908: 909: 910: 911: 912: 913: 914: 915: 916: 917: 918: 919: 920: 921: 922: 923: 924: 925: 926: 927: 928: 929: 930: 931: 932: 933: 934: 935: 936: 937: 938: 939: 940: 941: 942: 943: 944: 945: 946: 947: 948: 949: 950: 951: 952: 953: 954: 955: 956: 957: 958: 959: 960: 961: 962: 963: 964: 965: 966: 967: 968: 969: 970: 971: 972: 973: 974: 975: 976: 977: 978: 979: 980: 981: 982: 983: 984: 985: 986: 987: 988: 989: 990: 991: 992: 993: 994: 995: 996: 997: 998: 999: 1000: 1001: 1002: 1003: 1004: 1005: 1006: 1007: 1008: 1009: 1010: 1011: 1012: 1013: 1014: 1015: 1016: 1017: 1018: 1019: 1020: 1021: 1022: 1023: 1024: 1025: 1026: 1027: 1028: 1029: 1030: 1031: 1032: 1033: 1034: 1035: 1036: 1037: 1038: 1039: 1040: 1041: 1042: 1043: 1044: 1045: 1046: 1047: 1048: 1049: 1050: 1051: 1052: 1053: 1054: 1055: 1056: 1057: 1058: 1059: 1060: 1061: 1062: 1063: 1064: 1065: 1066: 1067: 1068: 1069: 1070: 1071: 1072: 1073: 1074: 1075: 1076: 1077: 1078: 1079: 1080: 1081: 1082: 1083: 1084: 1085: 1086: 1087: 1088: 1089: 1090: 1091: 1092: 1093: 1094: 1095: 1096: 1097: 1098: 1099: 1100: 1101: 1102: 1103: 1104: 1105: 1106: 1107: 1108: 1109: 1110: 1111: 1112: 1113: 1114: 1115: 1116: 1117: 1118: 1119: 1120: 1121: 1122: 1123: 1124: 1125: 1126: 1127: 1128: 1129: 1130: 1131: 1132: 1133: 1134: 1135: 1136: 1137: 1138: 1139: 1140: 1141: 1142: 1143: 1144: 1145: 1146: 1147: 1148: 1149: 1150: 1151: 1152: 1153: 1154: 1155: 1156: 1157: 1158: 1159: 1160: 1161: 1162: 1163: 1164: 1165: 1166: 1167: 1168: 1169: 1170: 1171: 1172: 1173: 1174: 1175: 1176: 1177: 1178: 1179: 1180: 1181: 1182: 1183: 1184: 1185: 1186: 1187: 1188: 1189: 1190: 1191: 1192: 1193: 1194: 1195: 1196: 1197: 1198: 1199: 1200: 1201: 1202: 1203: 1204: 1205: 1206: 1207: 1208: 1209: 1210: 1211: 1212: 1213: 1214: 1215: 1216: 1217: 1218: 1219: 1220: 1221: 1222: 1223: 1224: 1225: 1226: 1227: 1228: 1229: 1230: 1231: 1232: 1233: 1234: 1235: 1236: 1237: 1238: 1239: 1240: 1241: 1242: 1243: 1244: 1245: 1246: 1247: 1248: 1249: 1250: 1251: 1252: 1253: 1254: 1255: 1256: 1257: 1258: 1259: 1260: 1261: 1262: 1263: 1264: 1265: 1266: 1267: 1268: 1269: 1270: 1271: 1272: 1273: 1274: 1275: 1276: 1277: 1278: 1279: 1280: 1281: 1282: 1283: 1284: 1285: 1286: 1287: 1288: 1289: 1290: 1291: 1292: 1293: 1294: 1295: 1296: 1297: 1298: 1299: 1300: 1301: 1302: 1303: 1304: 1305: 1306: 1307: 1308: 1309: 1310: 1311: 1312: 1313: 1314: 1315: 1316: 1317: 1318: 1319: 1320: 1321: 1322: 1323: 1324: 1325: 1326: 1327: 1328: 1329: 1330: 1331: 1332: 1333: 1334: 1335: 1336: 1337: 1338: 1339: 1340: 1341: 1342: 1343: 1344: 1345: 1346: 1347: 1348: 1349: 1350: 1351: 1352: 1353: 1354: 1355: 1356: 1357: 1358: 1359: 1360: 1361: 1362: 1363: 1364: 1365: 1366: 1367: 1368: 1369: 1370: 1371: 1372: 1373: 1374: 1375: 1376: 1377: 1378: 1379: 1380: 1381: 1382: 1383: 1384: 1385: 1386: 1387: 1388: 1389: 1390: 1391: 1392: 1393: 1394: 1395: 1396: 1397: 1398: 1399: 1400: 1401: 1402: 1403: 1404: 1405: 1406: 1407: 1408: 1409: 1410: 1411: 1412: 1413: 1414: 1415: 1416: 1417: 1418: 1419: 1420: 1421: 1422: 1423: 1424: 1425: 1426: 1427: 1428: 1429: 1430: 1431: 1432: 1433: 1434: 1435: 1436: 1437: 1438: 1439: 1440: 1441: 1442: 1443: 1444: 1445: 1446: 1447: 1448: 1449: 1450: 1451: 1452: 1453: 1454: 1455: 1456: 1457: 1458: 1459: 1460: 1461: 1462: 1463: 1464: 1465: 1466: 1467: 1468: 1469: 1470: 1471: 1472: 1473: 1474: 1475: 1476: 1477: 1478: 1479: 1480: 1481: 1482: 1483: 1484: 1485: 1486: 1487: 1488: 1489: 1490: 1491: 1492: 1493: 1494: 1495: 1496: 1497: 1498: 1499: 1500: 1501: 1502: 1503: 1504: 1505: 1506: 1507: 1508: 1509: 1510: 1511: 1512: 1513: 1514: 1515: 1516: 1517: 1518: 1519: 1520: 1521: 1522: 1523: 1524: 1525: 1526: 1527: 1528: 1529: 1530: 1531: 1532: 1533: 1534: 1535: 1536: 1537: 1538: 1539: 1540: 1541: 1542: 1543: 1544: 1545: 1546: 1547: 1548: 1549: 1550: 1551: 1552: 1553: 1554: 1555: 1556: 1557: 1558: 1559: 1560: 1561: 1562: 1563: 1564: 1565: 1566: 1567: 1568: 1569: 1570: 1571: 1572: 1573: 1574: 1575: 1576: 1577: 1578: 1579: 1580: 1581: 1582: 1583: 1584: 1585: 1586: 1587: 1588: 1589: 1590: 1591: 1592: 1593: 1594: 1595: 1596: 1597: 1598: 1599: 1600: 1601: 1602: 1603: 1604: 1605: 1606: 1607: 1608: 1609: 1610: 1611: 1612: 1613: 1614: 1615: 1616: 1617: 1618: 1619: 1620: 1621: 1622: 1623: 1624: 1625: 1626: 1627: 1628: 1629: 1630: 1631: 1632: 1633: 1634: 1635: 1636: 1637: 1638: 1639: 1640: 1641: 1642: 1643: 1644: 1645: 1646: 1647: 1648: 1649: 1650: 1651: 1652: 1653: 1654: 1655: 1656: 1657: 1658: 1659: 1660: 1661: 1662: 1663: 1664: 1665: 1666: 1667: 1668: 1669: 1670: 1671: 1672: 1673: 1674: 1675: 1676: 1677: 1678: 1679: 1680: 1681: 1682: 1683: 1684: 1685: 1686: 1687: 1688: 1689: 1690: 1691: 1692: 1693: 1694: 1695: 1696: 1697: 1698: 1699: 1700: 1701: 1702: 1703: 1704: 1705: 1706: 1707: 1708: 1709: 1710: 1711: 1712: 1713: 1714: 1715: 1716: 1717: 1718: 1719: 1720: 1721: 1722: 1723: 1724: 1725: 1726: 1727: 1728: 1729: 1730: 1731: 1732: 1733: 1734: 1735: 1736: 1737: 1738: 1739: 1740: 1741: 1742: 1743: 1744: 1745: 1746: 1747: 1748: 1749: 1750: 1751: 1752: 1753: 1754: 1755: 1756: 1757: 1758: 1759: 1760: 1761: 1762: 1763: 1764: 1765: 1766: 1767: 1768: 1769: 1770: 1771: 1772: 1773: 1774: 1775: 1776: 1777: 1778: 1779: 1780: 1781: 1782: 1783: 1784: 1785: 1786: 1787: 1788: 1789: 1790: 1791: 1792: 1793: 1794: 1795: 1796: 1797: 1798: 1799: 1800: 1801: 1802: 1803: 1804: 1805: 1806: 1807: 1808: 1809: 1810: 1811: 1812: 1813: 1814: 1815: 1816: 1817: 1818: 1819: 1820: 1821: 1822: 1823: 1824: 1825: 1826: 1827: 1828: 1829: 1830: 1831: 1832: 1833: 1834: 1835: 1836: 1837: 1838: 1839: 1840: 1841: 1842: 1843: 1844: 1845: 1846: 1847: 1848: 1849: 1850: 1851: 1852: 1853: 1854: 1855: 1856: 1857: 1858: 1859: 1860: 1861: 1862: 1863: 1864: 1865: 1866: 1867: 1868: 1869: 1870: 1871: 1872: 1873: 1874: 1875: 1876: 1877: 1878: 1879: 1880: 1881: 1882: 1883: 1884: 1885: 1886: 1887: 1888: 1889: 1890: 1891: 1892: 1893: 1894: 1895: 1896: 1897: 1898: 1899: 1900: 1901: 1902: 1903: 1904: 1905: 1906: 1907: 1908: 1909: 1910: 1911: 1912: 1913: 1914: 1915: 1916: 1917: 1918: 1919: 1920: 1921: 1922: 1923: 1924: 1925: 1926: 1927: 1928: 1929: 1930: 1931: 1932: 1933: 1934: 1935: 1936: 1937: 1938: 1939: 1940: 1941: 1942: 1943: 1944: 1945: 1946: 1947: 1948: 1949: 1950: 1951: 1952: 1953: 1954: 1955: 1956: 1957: 1958: 1959: 1960: 1961: 1962: 1963: 1964: 1965: 1966: 1967: 1968: 1969: 1970: 1971: 1972: 1973: 1974: 1975: 1976: 1977: 1978: 1979: 1980: 1981: 1982: 1983: 1984: 1985: 1986: 1987: 1988: 1989: 1990: 1991: 1992: 1993: 1994: 1995: 1996: 1997: 1998: 1999: 2000: 2001: 2002: 2003: 2004: 2005: 2006: 2007: 2008: 2009: 2010: 2011: 2012: 2013: 2014: 2015: 2016: 2017: 2018: 2019: 2020: 2021: 2022: 2023: 2024: 2025: 2026: 2027: 2028: 2029: 2030: 2031: 2032: 2033: 2034: 2035: 2036: 2037: 2038: 2039: 2040: 2041: 2042: 2043: 2044: 2045: 2046: 2047: 2048: 2049: 2050: 2051: 2052: 2053: 2054: 2055: 2056: 2057: 2058: 2059: 2060: 2061: 2062: 2063: 2064: 2065: 2066: 2067: 2068: 2069: 2070: 2071: 2072: 2073: 2074: 2075: 2076: 2077: 2078: 2079: 2080: 2081: 2082: 2083: 2084: 2085: 2086: 2087: 2088: 2089: 2090: 2091: 2092: 2093: 2094: 2095: 2096: 2097: 2098: 2099: 2100: 2101: 2102: 2103: 2104: 2105: 2106: 2107: 2108: 2109: 2110: 2111: 2112: 2113: 2114: 2115: 2116: 2117: 2118: 2119: 2120: 2121: 2122: 2123: 2124: 2125: 2126: 2127: 2128: 2129: 2130: 2131: 2132: 2133: 2134: 2135: 2136: 2137: 2138: 2139: 2140: 2141: 2142: 2143: 2144: 2145: 2146: 2147: 2148: 2149: 2150: 2151: 2152: 2153: 2154: 2155: 2156: 2157: 2158: 2159: 2160: 2161: 2162: 2163: 2164: 2165: 2166: 2167: 2168: 2169: 2170: 2171: 2172: 2173: 2174: 2175: 2176: 2177: 2178: 2179: 2180: 2181: 2182: 2183: 2184: 2185: 2186: 2187: 2188: 2189: 2190: 2191: 2192: 2193: 2194: 2195: 2196: 2197: 2198: 2199: 2200: 2201: 2202: 2203: 2204: 2205: 2206: 2207: 2208: 2209: 2210: 2211: 2212: 2213: 2214: 2215: 2216: 2217: 2218: 2219: 2220: 2221: 2222: 2223: 2224: 2225: 2226: 2227: 2228: 2229: 2230: 2231: 2232: 2233: 2234: 2235: 2236: 2237: 2238: 2239: 2240: 2241: 2242: 2243: 2244: 2245: 2246: 2247: 2248: 2249: 2250: 2251: 2252: 2253: 2254: 2255: 2256: 2257: 2258: 2259: 2260: 2261: 2262: 2263: 2264: 2265: 2266: 2267: 2268: 2269: 2270: 2271: 2272: 2273: 2274: 2275: 2276: 2277: 2278: 2279: 2280: 2281: 2282: 2283: 2284: 2285: 2286: 2287: 2288: 2289: 2290: 2291: 2292: 2293: 2294: 2295: 2296: 2297: 2298: 2299: 2300: 2301: 2302: 2303: 2304: 2305: 2306: 2307: 2308: 2309: 2310: 2311: 2312: 2313: 2314: 2315: 2316: 2317: 2318: 2319: 2320: 2321: 2322: 2323: 2324: 2325: 2326: 2327: 2328: 2329: 2330: 2331: 2332: 2333: 2334: 2335: 2336: 2337: 2338: 2339: 2340: 2341: 2342: 2343: 2344: 2345: 2346: 2347: 2348: 2349: 2350: 2351: 2352: 2353: 2354: 2355: 2356: 2357: 2358: 2359: 2360: 2361: 2362: 2363: 2364: 2365: 2366: 2367: 2368: 2369: 2370: 2371: 2372: 2373: 2374: 2375: 2376: 2377: 2378: 2379: 2380: 2381: 2382: 2383: 2384: 2385: 2386: 2387: 2388: 2389: 2390: 2391: 2392: 2393: 2394: 2395: 2396: 2397: 2398: 2399: 2400: 2401: 2402: 2403: 2404: 2405: 2406: 2407: 2408: 2409: 2410: 2411: 2412: 2413: 2414: 2415: 2416: 2417: 2418: 2419: 2420: 2421: 2422: 2423: 2424: 2425: 2426: 2427: 2428: 2429: 2430: 2431: 2432: 2433: 2434: 2435: 2436: 2437: 2438: 2439: 2440: 2441: 2442: 2443: 2444: 2445: 2446: 2447: 2448: 2449: 2450: 2451: 2452: 2453: 2454: 2455: 2456: 2457: 2458: 2459: 2460: 2461: 2462: 2463: 2464: 2465: 2466: 2467: 2468: 2469: 2470: 2471: 2472: 2473: 2474: 2475: 2476: 2477: 2478: 2479: 2480: 2481: 2482: 2483: 2484: 2485: 2486: 2487: 2488: 2489: 2490: 2491: 2492: 2493: 2494: 2495: 2496: 2497: 2498: 2499: 2500: 2501: 2502: 2503: 2504: 2505: 2506: 2507: 2508: 2509: 2510: 2511: 2512: 2513: 2514: 2515: 2516: 2517: 2518: 2519: 2520: 2521: 2522: 2523: 2524: 2525: 2526: 2527: 2528: 2529: 2530: 2531: 2532: 2533: 2534: 2535: 2536: 2537: 2538: 2539: 2540: 2541: 2542: 2543: 2544: 2545: 2546: 2547: 2548: 2549: 2550: 2551: 2552: 2553: 2554: 2555: 2556: 2557: 2558: 2559: 2560: 2561: 2562: 2563: 2564: 2565: 2566: 2567: 2568: 2569: 2570: 2571: 2572: 2573: 2574: 2575: 2576: 2577: 2578: 2579: 2580: 2581: 2582: 2583: 2584: 2585: 2586: 2587: 2588: 2589: 2590: 2591: 2592: 2593: 2594: 2595: 2596: 2597: 2598: 2599: 2600: 2601: 2602: 2603: 2604: 2605: 2606: 2607: 2608: 2609: 2610: 2611: 2612: 2613: 2614: 2615: 2616: 2617: 2618: 2619: 2620: 2621: 2622: 2623: 2624: 2625: 2626: 2627: 2628: 2629: 2630: 2631: 2632: 2633: 2634: 2635: 2636: 2637: 2638: 2639: 2640: 2641: 2642: 2643: 2644: 2645: 2646: 2647: 2648: 2649: 2650: 2651: 2652: 2653: 2654: 2655: 2656: 2657: 2658: 2659: 2660: 2661: 2662: 2663: 2664: 2665: 2666: 2667: 2668: 2669: 2670: 2671: 2672: 2673: 2674: 2675: 2676: 2677: 2678: 2679: 2680: 2681: 2682: 2683: 2684: 2685: 2686: 2687: 2688: 2689: 2690: 2691: 2692: 2693: 2694: 2695: 2696: 2697: 2698: 2699: 2700: 2701: 2702: 2703: 2704: 2705: 2706: 2707: 2708: 2709: 2710: 2711: 2712: 2713: 2714: 2715: 2716: 2717: 2718: 2719: 2720: 2721: 2722: 2723: 2724: 2725: 2726: 2727: 2728: 2729: 2730: 2731: 2732: 2733: 2734: 2735: 2736: 2737: 2738: 2739: 2740: 2741: 2742: 2743: 2744: 2745: 2746: 2747: 2748: 2749: 2750: 2751: 2752: 2753: 2754: 2755: 2756: 2757: 2758: 2759: 2760: 2761: 2762: 2763: 2764: 2765: 2766: 2767: 2768: 2769: 2770: 2771: 2772: 2773: 2774: 2775: 2776: 2777: 2778: 2779: 2780: 2781: 2782: 2783: 2784: 2785: 2786: 2787: 2788: 2789: 2790: 2791: 2792: 2793: 2794: 2795: 2796: 2797: 2798: 2799: 2800: 2801: 2802: 2803: 2804: 2805: 2806: 2807: 2808: 2809: 2810: 2811: 2812: 2813: 2814: 2815: 2816: 2817: 2818: 2819: 2820: 2821: 2822: 2823: 2824: 2825: 2826: 2827: 2828: 2829: 2830: 2831: 2832: 2833: 2834: 2835: 2836: 2837: 2838: 2839: 2840: 2841: 2842: 2843: 2844: 2845: 2846: 2847: 2848: 2849: 2850: 2851: 2852: 2853: 2854: 2855: 2856: 2857: 2858: 2859: 2860: 2861: 2862: 2863: 2864: 2865: 2866: 2867: 2868: 2869: 2870: 2871: 2872: 2873: 2874: 2875: 2876: 2877: 2878: 2879: 2880: 2881: 2882: 2883: 2884: 2885: 2886: 2887: 2888: 2889: 2890: 2891: 2892: 2893: 2894: 2895: 2896: 2897: 2898: 2899: 2900: 2901: 2902: 2903: 2904: 2905: 2906: 2907: 2908: 2909: 2910: 2911: 2912: 2913: 2914: 2915: 2916: 2917: 2918: 2919: 2920: 2921: 2922: 2923: 2924: 2925: 2926: 2927: 2928: 2929: 2930: 2931: 2932: 2933: 2934: 2935: 2936: 2937: 2938: 2939: 2940: 2941: 2942: 2943: 2944: 2945: 2946: 2947: 2948: 2949: 2950: 2951: 2952: 2953: 2954: 2955: 2956: 2957: 2958: 2959: 2960: 2961: 2962: 2963: 2964: 2965: 2966: 2967: 2968: 2969: 2970: 2971: 2972: 2973: 2974: 2975: 2976: 2977: 2978: 2979: 2980: 2981: 2982: 2983: 2984: 2985: 2986: 2987: 2988: 2989: 2990: 2991: 2992: 2993: 2994: 2995: 2996: 2997: 2998: 2999: 3000: 3001: 3002: 3003: 3004: 3005: 3006: 3007: 3008: 3009: 3010: 3011: 3012: 3013: 3014: 3015: 3016: 3017: 3018: 3019: 3020: 3021: 3022: 3023: 3024: 3025: 3026: 3027: 3028: 3029: 3030: 3031: 3032: 3033: 3034: 3035: 3036: 3037: 3038: 3039: 3040: 3041: 3042: 3043: 3044: 3045: 3046: 3047: 3048: 3049: 3050: 3051: 3052: 3053: 3054: 3055: 3056: 3057: 3058: 3059: 3060: 3061: 3062: 3063: 3064: 3065: 3066: 3067: 3068: 3069: 3070: 3071: 3072: 3073: 3074: 3075: 3076: 3077: 3078: 3079: 3080: 3081: 3082: 3083: 3084: 3085: 3086: 3087: 3088: 3089: 3090: 3091: 3092: 3093: 3094: 3095: 3096: 3097: 3098: 3099: 3100: 3101: 3102: 3103: 3104: 3105: 3106: 3107: 3108: 3109: 3110: 3111: 3112: 3113: 3114: 3115: 3116: 3117: 3118: 3119: 3120: 3121: 3122: 3123: 3124: 3125: 3126: 3127: 3128: 3129: 3130: 3131: 3132: 3133: 3134: 3135: 3136: 3137: 3138: 3139: 3140: 3141: 3142: 3143: 3144: 3145: 3146: 3147: 3148: 3149: 3150: 3151: 3152: 3153: 3154: 3155: 3156: 3157: 3158: 3159: 3160: 3161: 3162: 3163: 3164: 3165: 3166: 3167: 3168: 3169: 3170: 3171: 3172: 3173: 3174: 3175: 3176: 3177: 3178: 3179: 3180: 3181: 3182: 3183: 3184: 3185: 3186: 3187: 3188: 3189: 3190: 3191: 3192: 3193: 3194: 3195: 3196: 3197: 3198: 3199: 3200: 3201: 3202: 3203: 3204: 3205: 3206: 3207: 3208: 3209: 3210: 3211: 3212: 3213: 3214: 3215: 3216: 3217: 3218: 3219: 3220: 3221: 3222: 3223: 3224: 3225: 3226: 3227: 3228: 3229: 3230: 3231: 3232: 3233: 3234: 3235: 3236: 3237: 3238: 3239: 3240: 3241: 3242: 3243: 3244: 3245: 3246: 3247: 3248: 3249: 3250: 3251: 3252: 3253: 3254: 3255: 3256: 3257: 3258: 3259: 3260: 3261: 3262: 3263: 3264: 3265: 3266: 3267: 3268: 3269: 3270: 3271: 3272: 3273: 3274: 3275: 3276: 3277: 3278: 3279: 3280: 3281: 3282: 3283: 3284: 3285: 3286: 3287: 3288: 3289: 3290: 3291: 3292: 3293: 3294: 3295: 3296: 3297: 3298: 3299: 3300: 3301: 3302: 3303: 3304: 3305: 3306: 3307: 3308: 3309: 3310: 3311: 3312: 3313: 3314: 3315: 3316: 3317: 3318: 3319: 3320: 3321: 3322: 3323: 3324: 3325: 3326: 3327: 3328: 3329: 3330: 3331: 3332: 3333: 3334: 3335: 3336: 3337: 3338: 3339: 3340: 3341: 3342: 3343: 3344: 3345: 3346: 3347: 3348: 3349: 3350: 3351: 3352: 3353: 3354: 3355: 3356: 3357: 3358: 3359: 3360: 3361: 3362: 3363: 3364: 3365: 3366: 3367: 3368: 3369: 3370: 3371: 3372: 3373: 3374: 3375: 3376: 3377: 3378: 3379: 3380: 3381: 3382: 3383: 3384: 3385: 3386: 3387: 3388: 3389: 3390: 3391: 3392: 3393: 3394: 3395: 3396: 3397: 3398: 3399: 3400: 3401: 3402: 3403: 3404: 3405: 3406: 3407: 3408: 3409: 3410: 3411: 3412: 3413: 3414: 3415: 3416: 3417: 3418: 3419: 3420: 3421: 3422: 3423: 3424: 3425: 3426: 3427: 3428: 3429: 3430: 3431: 3432: 3433: 3434: 3435: 3436: 3437: 3438: 3439: 3440: 3441: 3442: 3443: 3444: 3445: 3446: 3447: 3448: 3449: 3450: 3451: 3452: 3453: 3454: 3455: 3456: 3457: 3458: 3459: 3460: 3461: 3462: 3463: 3464: 3465: 3466: 3467: 3468: 3469: 3470: 3471: 3472: 3473: 3474: 3475: 3476: 3477: 3478: 3479: 3480: 3481: 3482: 3483: 3484: 3485: 3486: 3487: 3488: 3489: 3490: 3491: 3492: 3493: 3494: 3495: 3496: 3497: 3498: 3499: 3500: 3501: 3502: 3503: 3504: 3505: 3506: 3507: 3508: 3509: 3510: 3511: 3512: 3513: 3514: 3515: 3516: 3517: 3518: 3519: 3520: 3521: 3522: 3523: 3524: 3525: 3526: 3527: 3528: 3529: 3530: 3531: 3532: 3533: 3534: 3535: 3536: 3537: 3538: 3539: 3540: 3541: 3542: 3543: 3544: 3545: 3546: 3547: 3548: 3549: 3550: 3551: 3552: 3553: 3554: 3555: 3556: 3557: 3558: 3559: 3560: 3561: 3562: 3563: 3564: 3565: 3566: 3567: 3568: 3569: 3570: 3571: 3572: 3573: 3574: 3575: 3576: 3577: 3578: 3579: 3580: 3581: 3582: 3583: 3584: 3585: 3586: 3587: 3588: 3589: 3590: 3591: 3592: 3593: 3594: 3595: 3596: 3597: 3598: 3599: 3600: 3601: 3602: 3603: 3604: 3605: 3606: 3607: 3608: 3609: 3610: 3611: 3612: 3613: 3614: 3615: 3616: 3617: 3618: 3619: 3620: 3621: 3622: 3623: 3624: 3625: 3626: 3627: 3628: 3629: 3630: 3631: 3632: 3633: 3634: 3635: 3636: 3637: 3638: 3639: 3640: 3641: 3642: 3643: 3644: 3645: 3646: 3647: 3648: 3649: 3650: 3651: 3652: 3653: 3654: 3655: 3656: 3657: 3658: 3659: 3660: 3661: 3662: 3663: 3664: 3665: 3666: 3667: 3668: 3669: 3670: 3671: 3672: 3673: 3674: 3675: 3676: 3677: 3678: 3679: 3680: 3681: 3682: 3683: 3684: 3685: 3686: 3687: 3688: 3689: 3690: 3691: 3692: 3693: 3694: 3695: 3696: 3697: 3698: 3699: 3700: 3701: 3702: 3703: 3704: 3705: 3706: 3707: 3708: 3709: 3710: 3711: 3712: 3713: 3714: 3715: 3716: 3717: 3718: 3719: 3720: 3721: 3722: 3723: 3724: 3725: 3726: 3727: 3728: 3729: 3730: 3731: 3732: 3733: 3734: 3735: 3736: 3737: 3738: 3739: 3740: 3741: 3742: 3743: 3744: 3745: 3746: 3747: 3748: 3749: 3750: 3751: 3752: 3753: 3754: 3755: 3756: 3757: 3758: 3759: 3760: 3761: 3762: 3763: 3764: 3765: 3766: 3767: 3768: 3769: 3770: 3771: 3772: 3773: 3774: 3775: 3776: 3777: 3778: 3779: 3780: 3781: 3782: 3783: 3784: 3785: 3786: 3787: 3788: 3789: 3790: 3791: 3792: 3793: 3794: 3795: 3796: 3797: 3798: 3799: 3800: 3801: 3802: 3803: 3804: 3805: 3806: 3807: 3808: 3809: 3810: 3811: 3812: 3813: 3814: 3815: 3816: 3817: 3818: 3819: 3820: 3821: 3822: 3823: 3824: 3825: 3826: 3827: 3828: 3829: 3830: 3831: 3832: 3833: 3834: 3835: 3836: 3837: 3838: 3839: 3840: 3841: 3842: 3843: 3844: 3845: 3846: 3847: 3848: 3849: 3850: 3851: 3852: 3853: 3854: 3855: 3856: 3857: 3858: 3859: 3860: 3861: 3862: 3863: 3864: 3865: 3866: 3867: 3868: 3869: 3870: 3871: 3872: 3873: 3874: 3875: 3876: 3877: 3878: 3879: 3880: 3881: 3882: 3883: 3884: 3885: 3886: 3887: 3888: 3889: 3890: 3891: 3892: 3893: 3894: 3895: 3896: 3897: 3898: 3899: 3900: 3901: 3902: 3903: 3904: 3905: 3906: 3907: 3908: 3909: 3910: 3911: 3912: 3913: 3914: 3915: 3916: 3917: 3918: 3919: 3920: 3921: 3922: 3923: 3924: 3925: 3926: 3927: 3928: 3929: 3930: 3931: 3932: 3933: 3934: 3935: 3936: 3937: 3938: 3939: 3940: 3941: 3942: 3943: 3944: 3945: 3946: 3947: 3948: 3949: 3950: 3951: 3952: 3953: 3954: 3955: 3956: 3957: 3958: 3959: 3960: 3961: 3962: 3963: 3964: 3965: 3966: 3967: 3968: 3969: 3970: 3971: 3972: 3973: 3974: 3975: 3976: 3977: 3978: 3979: 3980: 3981: 3982: 3983: 3984: 3985: 3986: 3987: 3988: 3989: 3990: 3991: 3992: 3993: 3994: 3995: 3996: 3997: 3998: 3999: 4000: 4001: 4002: 4003: 4004: 4005: 4006: 4007: 4008: 4009: 4010: 4011: 4012: 4013: 4014: 4015: 4016: 4017: 4018: 4019: 4020: 4021: 4022: 4023: 4024: 4025: 4026: 4027: 4028: 4029: 4030: 4031: 4032: 4033: 4034: 4035: 4036: 4037: 4038: 4039: 4040: 4041: 4042: 4043: 4044: 4045: 4046: 4047: 4048: 4049: 4050: 4051: 4052: 4053: 4054: 4055: 4056: 4057: 4058: 4059: 4060: 4061: 4062: 4063: 4064: 4065: 4066: 4067: 4068: 4069: 4070: 4071: 4072: 4073: 4074: 4075: 4076: 4077: 4078: 4079: 4080: 4081: 4082: 4083: 4084: 4085: 4086: 4087: 4088: 4089: 4090: 4091: 4092: 4093: 4094: 4095: 4096: 4097: 4098: 4099: 4100: 4101: 4102: 4103: 4104: 4105: 4106: 4107: 4108: 4109: 4110: 4111: 4112: 4113: 4114: 4115: 4116: 4117: 4118: 4119: 4120: 4121: 4122: 4123: 4124: 4125: 4126: 4127: 4128: 4129: 4130: 4131: 4132: 4133: 4134: 4135: 4136: 4137: 4138: 4139: 4140: 4141: 4142: 4143: 4144: 4145: 4146: 4147: 4148: 4149: 4150: 4151: 4152: 4153: 4154: 4155: 4156: 4157: 4158: 4159: 4160: 4161: 4162: 4163: 4164: 4165: 4166: 4167: 4168: 4169: 4170: 4171: 4172: 4173: 4174: 4175: 4176: 4177: 4178: 4179: 4180: 4181: 4182: 4183: 4184: 4185: 4186: 4187: 4188: 4189: 4190: 4191: 4192: 4193: 4194: 4195: 4196: 4197: 4198: 4199: 4200: 4201: 4202: 4203: 4204: 4205: 4206: 4207: 4208: 4209: 4210: 4211: 4212: 4213: 4214: 4215: 4216: 4217: 4218: 4219: 4220: 4221: 4222: 4223: 4224: 4225: 4226: 4227: 4228: 4229: 4230: 4231: 4232: 4233: 4234: 4235: 4236: 4237: 4238: 4239: 4240: 4241: 4242: 4243: 4244: 4245: 4246: 4247: 4248: 4249: 4250: 4251: 4252: 4253: 4254: 4255: 4256: 4257: 4258: 4259: 4260: 4261: 4262: 4263: 4264: 4265: 4266: 4267: 4268: 4269: 4270: 4271: 4272: 4273: 4274: 4275: 4276: 4277: 4278: 4279: 4280: 4281: 4282: 4283: 4284: 4285: 4286: 4287: 4288: 4289: 4290: 4291: 4292: 4293: 4294: 4295: 4296: 4297: 4298: 4299: 4300: 4301: 4302: 4303: 4304: 4305: 4306: 4307: 4308: 4309: 4310: 4311: 4312: 4313: 4314: 4315: 4316: 4317: 4318: 4319: 4320: 4321: 4322: 4323: 4324: 4325: 4326: 4327: 4328: 4329: 4330: 4331: 4332: 4333: 4334: 4335: 4336: 4337: 4338: 4339: 4340: 4341: 4342: 4343: 4344: 4345: 4346: 4347: 4348: 4349: 4350: 4351: 4352: 4353: 4354: 4355: 4356: 4357: 4358: 4359: 4360: 4361: 4362: 4363: 4364: 4365: 4366: 4367: 4368: 4369: 4370: 4371: 4372: 4373: 4374: 4375: 4376: 4377: 4378: 4379: 4380: 4381: 4382: 4383: 4384: 4385: 4386: 4387: 4388: 4389: 4390: 4391: 4392: 4393: 4394: 4395: 4396: 4397: 4398: 4399: 4400: 4401: 4402: 4403: 4404: 4405: 4406: 4407: 4408: 4409: 4410: 4411: 4412: 4413: 4414: 4415: 4416: 4417: 4418: 4419: 4420: 4421: 4422: 4423: 4424: 4425: 4426: 4427: 4428: 4429: 4430: 4431: 4432: 4433: 4434: 4435: 4436: 4437: 4438: 4439: 4440: 4441: 4442: 4443: 4444: 4445: 4446: 4447: 4448: 4449: 4450: 4451: 4452: 4453: 4454: 4455: 4456: 4457: 4458: 4459: 4460: 4461: 4462: 4463: 4464: 4465: 4466: 4467: 4468: 4469: 4470: 4471: 4472: 4473: 4474: 4475: 4476: 4477: 4478: 4479: 4480: 4481: 4482: 4483: 4484: 4485: 4486: 4487: 4488: 4489: 4490: 4491: 4492: 4493: 4494: 4495: 4496: 4497: 4498: 4499: 4500: 4501: 4502: 4503: 4504: 4505: 4506: 4507: 4508: 4509: 4510: 4511: 4512: 4513: 4514: 4515: 4516: 4517: 4518: 4519: 4520: 4521: 4522: 4523: 4524: 4525: 4526: 4527: 4528: 4529: 4530: 4531: 4532: 4533: 4534: 4535: 4536: 4537: 4538: 4539: 4540: 4541: 4542: 4543: 4544: 4545: 4546: 4547: 4548: 4549: 4550: 4551: 4552: 4553: 4554: 4555: 4556: 4557: 4558: 4559: 4560: 4561: 4562: 4563: 4564: 4565: 4566: 4567: 4568: 4569: 4570: 4571: 4572: 4573: 4574: 4575: 4576: 4577: 4578: 4579: 4580: 4581: 4582: 4583: 4584: 4585: 4586: 4587: 4588: 4589: 4590: 4591: 4592: 4593: 4594: 4595: 4596: 4597: 4598: 4599: 4600: 4601: 4602: 4603: 4604: 4605: 4606: 4607: 4608: 4609: 4610: 4611: 4612: 4613: 4614: 4615: 4616: 4617: 4618: 4619: 4620: 4621: 4622: 4623: 4624: 4625: 4626: 4627: 4628: 4629: 4630: 4631: 4632: 4633: 4634: 4635: 4636: 4637: 4638: 4639: 4640: 4641: 4642: 4643: 4644: 4645: 4646: 4647: 4648: 4649: 4650: 4651: 4652: 4653: 4654: 4655: 4656: 4657: 4658: 4659: 4660: 4661: 4662: 4663: 4664: 4665: 4666: 4667: 4668: 4669: 4670: 4671: 4672: 4673: 4674: 4675: 4676: 4677: 4678: 4679: 4680: 4681: 4682: 4683: 4684: 4685: 4686: 4687: 4688: 4689: 4690: 4691: 4692: 4693: 4694: 4695: 4696: 4697: 4698: 4699: 4700: 4701: 4702: 4703: 4704: 4705: 4706: 4707: 4708: 4709: 4710: 4711: 4712: 4713: 4714: 4715: 4716: 4717: 4718: 4719: 4720: 4721: 4722: 4723: 4724: 4725: 4726: 4727: 4728: 4729: 4730: 4731: 4732: 4733: 4734: 4735: 4736: 4737: 4738: 4739: 4740: 4741: 4742: 4743: 4744: 4745: 4746: 4747: 4748: 4749: 4750: 4751: 4752: 4753: 4754: 4755: 4756: 4757: 4758: 4759: 4760: 4761: 4762: 4763: 4764: 4765: 4766: 4767: 4768: 4769: 4770: 4771: 4772: 4773: 4774: 4775: 4776: 4777: 4778: 4779: 4780: 4781: 4782: 4783: 4784: 4785: 4786: 4787: 4788: 4789: 4790: 4791: 4792: 4793: 4794: 4795: 4796: 4797: 4798: 4799: 4800: 4801: 4802: 4803: 4804: 4805: 4806: 4807: 4808: 4809: 4810: 4811: 4812: 4813: 4814: 4815: 4816: 4817: 4818: 4819: 4820: 4821: 4822: 4823: 4824: 4825: 4826: 4827: 4828: 4829: 4830: 4831: 4832: 4833: 4834: 4835: 4836: 4837: 4838: 4839: 4840: 4841: 4842: 4843: 4844: 4845: 4846: 4847: 4848: 4849: 4850: 4851: 4852: 4853: 4854: 4855: 4856: 4857: 4858: 4859: 4860: 4861: 4862: 4863: 4864: 4865: 4866: 4867: 4868: 4869: 4870: 4871: 4872: 4873: 4874: 4875: 4876: 4877: 4878: 4879: 4880: 4881: 4882: 4883: 4884: 4885: 4886: 4887: 4888: 4889: 4890: 4891: 4892: 4893: 4894: 4895: 4896: 4897: 4898: 4899: 4900: 4901: 4902: 4903: 4904: 4905: 4906: 4907: 4908: 4909: 4910: 4911: 4912: 4913: 4914: 4915: 4916: 4917: 4918: 4919: 4920: 4921: 4922: 4923: 4924: 4925: 4926: 4927: 4928: 4929: 4930: 4931: 4932: 4933: 4934: 4935: 4936: 4937: 4938: 4939: 4940: 4941: 4942: 4943: 4944: 4945: 4946: 4947: 4948: 4949: 4950: 4951: 4952: 4953: 4954: 4955: 4956: 4957: 4958: 4959: 4960: 4961: 4962: 4963: 4964: 4965: 4966: 4967: 4968: 4969: 4970: 4971: 4972: 4973: 4974: 4975: 4976: 4977: 4978: 4979: 4980: 4981: 4982: 4983: 4984: 4985: 4986: 4987: 4988: 4989: 4990: 4991: 4992: 4993: 4994: 4995: 4996: 4997: 4998: 4999: 5000: 5001: 5002: 5003: 5004: 5005: 5006: 5007: 5008: 5009: 5010: 5011: 5012: 5013: 5014: 5015: 5016: 5017: 5018: 5019: 5020: 5021: 5022: 5023: 5024: 5025: 5026: 5027: 5028: 5029: 5030: 5031: 5032: 5033: 5034: 5035: 5036: 5037: 5038: 5039: 5040: 5041: 5042: 5043: 5044: 5045: 5046: 5047: 5048: 5049: 5050: 5051: 5052: 5053: 5054: 5055: 5056: 5057: 5058: 5059: 5060: 5061: 5062: 5063: 5064: 5065: 5066: 5067: 5068: 5069: 5070: 5071: 5072: 5073: 5074: 5075: 5076: 5077: 5078: 5079: 5080: 5081: 5082: 5083: 5084: 5085: 5086: 5087: 5088: 5089: 5090: 5091: 5092: 5093: 5094: 5095: 5096: 5097: 5098: 5099: 5100: 5101: 5102: 5103: 5104: 5105: 5106: 5107: 5108: 5109: 5110: 5111: 5112: 5113: 5114: 5115: 5116: 5117: 5118: 5119: 5120: 5121: 5122: 5123: 5124: 5125: 5126: 5127: 5128: 5129: 5130: 5131: 5132: 5133: 5134: 5135: 5136: 5137: 5138: 5139: 5140: 5141: 5142: 5143: 5144: 5145: 5146: 5147: 5148: 5149: 5150: 5151: 5152: 5153: 5154: 5155: 5156: 5157: 5158: 5159: 5160: 5161: 5162: 5163: 5164: 5165: 5166: 5167: 5168: 5169: 5170: 5171: 5172: 5173: 5174: 5175: 5176: 5177: 5178: 5179: 5180: 5181: 5182: 5183: 5184: 5185: 5186: 5187: 5188: 5189: 5190: 5191: 5192: 5193: 5194: 5195: 5196: 5197: 5198: 5199: 5200: 5201: 5202: 5203: 5204: 5205: 5206: 5207: 5208: 5209: 5210: 5211: 5212: 5213: 5214: 5215: 5216: 5217: 5218: 5219: 5220: 5221: 5222: 5223: 5224: 5225: 5226: 5227: 5228: 5229: 5230: 5231: 5232: 5233: 5234: 5235: 5236: 5237: 5238: 5239: 5240: 5241: 5242: 5243: 5244: 5245: 5246: 5247: 5248: 5249: 5250: 5251: 5252: 5253: 5254: 5255: 5256: 5257: 5258: 5259: 5260: 5261: 5262: 5263: 5264: 5265: 5266: 5267: 5268: 5269: 5270: 5271: 5272: 5273: 5274: 5275: 5276: 5277: 5278: 5279: 5280: 5281: 5282: 5283: 5284: 5285: 5286: 5287: 5288: 5289: 5290: 5291: 5292: 5293: 5294: 5295: 5296: 5297: 5298: 5299: 5300: 5301: 5302: 5303: 5304: 5305: 5306: 5307: 5308: 5309: 5310: 5311: 5312: 5313: 5314: 5315: 5316: 5317: 5318: 5319: 5320: 5321: 5322: 5323: 5324: 5325: 5326: 5327: 5328: 5329: 5330: 5331: 5332: 5333: 5334: 5335: 5336: 5337: 5338: 5339: 5340: 5341: 5342: 5343: 5344: 5345: 5346: 5347: 5348: 5349: 5350: 5351: 5352: 5353: 5354: 5355: 5356: 5357: 5358: 5359: 5360: 5361: 5362: 5363: 5364: 5365: 5366: 5367: 5368: 5369: 5370: 5371: 5372: 5373: 5374: 5375: 5376: 5377: 5378: 5379: 5380: 5381: 5382: 5383: 5384: 5385: 5386: 5387: 5388: 5389: 5390: 5391: 5392: 5393: 5394: 5395: 5396: 5397: 5398: 5399: 5400: 5401: 5402: 5403: 5404: 5405: 5406: 5407: 5408: 5409: 5410: 5411: 5412: 5413: 5414: 5415: 5416: 5417: 5418: 5419: 5420: 5421: 5422: 5423: 5424: 5425: 5426: 5427: 5428: 5429: 5430: 5431: 5432: 5433: 5434: 5435: 5436: 5437: 5438: 5439: 5440: 5441: 5442: 5443: 5444: 5445: 5446: 5447: 5448: 5449: 5450: 5451: 5452: 5453: 5454: 5455: 5456: 5457: 5458: 5459: 5460: 5461: 5462: 5463: 5464: 5465: 5466: 5467: 5468: 5469: 5470: 5471: 5472: 5473: 5474: 5475: 5476: 5477: 5478: 5479: 5480: 5481: 5482: 5483: 5484: 5485: 5486: 5487: 5488: 5489: 5490: 5491: 5492: 5493: 5494: 5495: 5496: 5497: 5498: 5499: 5500: 5501: 5502: 5503: 5504: 5505: 5506: 5507: 5508: 5509: 5510: 5511: 5512: 5513: 5514: 5515: 5516: 5517: 5518: 5519: 5520: 5521: 5522: 5523: 5524: 5525: 5526: 5527: 5528: 5529: 5530: 5531: 5532: 5533: 5534: 5535: 5536: 5537: 5538: 5539: 5540: 5541: 5542: 5543: 5544: 5545: 5546: 5547: 5548: 5549: 5550: 5551: 5552: 5553: 5554: 5555: 5556: 5557: 5558: 5559: 5560: 5561: 5562: 5563: 5564: 5565: 5566: 5567: 5568: 5569: 5570: 5571: 5572: 5573: 5574: 5575: 5576: 5577: 5578: 5579: 5580: 5581: 5582: 5583: 5584: 5585: 5586: 5587: 5588: 5589: 5590: 5591: 5592: 5593: 5594: 5595: 5596: 5597: 5598: 5599: 5600: 5601: 5602: 5603: 5604: 5605: 5606: 5607: 5608: 5609: 5610: 5611: 5612: 5613: 5614: 5615: 5616: 5617: 5618: 5619: 5620: 5621: 5622: 5623: 5624: 5625: 5626: 5627: 5628: 5629: 5630: 5631: 5632: 5633: 5634: 5635: 5636: 5637: 5638: 5639: 5640: 5641: 5642: 5643: 5644: 5645: 5646: 5647: 5648: 5649: 5650: 5651: 5652: 5653: 5654: 5655: 5656: 5657: 5658: 5659: 5660: 5661: 5662: 5663: 5664: 5665: 5666: 5667: 5668: 5669: 5670: 5671: 5672: 5673: 5674: 5675: 5676: 5677: 5678: 5679: 5680: 5681: 5682: 5683: 5684: 5685: 5686: 5687: 5688: 5689: 5690: 5691: 5692: 5693: 5694: 5695: 5696: 5697: 5698: 5699: 5700: 5701: 5702: 5703: 5704: 5705: 5706: 5707: 5708: 5709: 5710: 5711: 5712: 5713: 5714: 5715: 5716: 5717: 5718: 5719: 5720: 5721: 5722: 5723: 5724: 5725: 5726: 5727: 5728: 5729: 5730: 5731: 5732: 5733: 5734: 5735: 5736: 5737: 5738: 5739: 5740: 5741: 5742: 5743: 5744: 5745: 5746: 5747: 5748: 5749: 5750: 5751: 5752: 5753: 5754: 5755: 5756: 5757: 5758: 5759: 5760: 5761: 5762: 5763: 5764: 5765: 5766: 5767: 5768: 5769: 5770: 5771: 5772: 5773: 5774: 5775: 5776: 5777: 5778: 5779: 5780: 5781: 5782: 5783: 5784: 5785: 5786: 5787: 5788: 5789: 5790: 5791: 5792: 5793: 5794: 5795: 5796: 5797: 5798: 5799: 5800: 5801: 5802: 5803: 5804: 5805: 5806: 5807: 5808: 5809: 5810: 5811: 5812: 5813: 5814: 5815: 5816: 5817: 5818: 5819: 5820: 5821: 5822: 5823: 5824: 5825: 5826: 5827: 5828: 5829: 5830: 5831: 5832: 5833: 5834: 5835: 5836: 5837: 5838: 5839: 5840: 5841: 5842: 5843: 5844: 5845: 5846: 5847: 5848: 5849: 5850: 5851: 5852: 5853: 5854: 5855: 5856: 5857: 5858: 5859: 5860: 5861: 5862: 5863: 5864: 5865: 5866: 5867: 5868: 5869: 5870: 5871: 5872: 5873: 5874: 5875: 5876: 5877: 5878: 5879: 5880: 5881: 5882: 5883: 5884: 5885: 5886: 5887: 5888: 5889: 5890: 5891: 5892: 5893: 5894: 5895: 5896: 5897: 5898: 5899: 5900: 5901: 5902: 5903: 5904: 5905: 5906: 5907: 5908: 5909: 5910: 5911: 5912: 5913: 5914: 5915: 5916: 5917: 5918: 5919: 5920: 5921: 5922: 5923: 5924: 5925: 5926: 5927: 5928: 5929: 5930: 5931: 5932: 5933: 5934: 5935: 5936: 5937: 5938: 5939: 5940: 5941: 5942: 5943: 5944: 5945: 5946: 5947: 5948: 5949: 5950: 5951: 5952: 5953: 5954: 5955: 5956: 5957: 5958: 5959: 5960: 5961: 5962: 5963: 5964: 5965: 5966: 5967: 5968: 5969: 5970: 5971: 5972: 5973: 5974: 5975: 5976: 5977: 5978: 5979: 5980: 5981: 5982: 5983: 5984: 5985: 5986: 5987: 5988: 5989: 5990: 5991: 5992: 5993: 5994: 5995: 5996: 5997: 5998: 5999: 6000: 6001: 6002: 6003: 6004: 6005: 6006: 6007: 6008: 6009: 6010: 6011: 6012: 6013: 6014: 6015: 6016: 6017: 6018: 6019: 6020: 6021: 6022: 6023: 6024: 6025: 6026: 6027: 6028: 6029: 6030: 6031: 6032: 6033: 6034: 6035: 6036: 6037: 6038: 6039: 6040: 6041: 6042: 6043: 6044: 6045: 6046: 6047: 6048: 6049: 6050: 6051: 6052: 6053: 6054: 6055: 6056: 6057: 6058: 6059: 6060: 6061: 6062: 6063: 6064: 6065: 6066: 6067: 6068: 6069: 6070: 6071: 6072: 6073: 6074: 6075: 6076: 6077: 6078: 6079: 6080: 6081: 6082: 6083: 6084: 6085: 6086: 6087: 6088: 6089: 6090: 6091: 6092: 6093: 6094: 6095: 6096: 6097: 6098: 6099: 6100: 6101: 6102: 6103: 6104: 6105: 6106: 6107: 6108: 6109: 6110: 6111: 6112: 6113: 6114: 6115: 6116: 6117: 6118: 6119: 6120: 6121: 6122: 6123: 6124: 6125: 6126: 6127: 6128: 6129: 6130: 6131: 6132: 6133: 6134: 6135: 6136: 6137: 6138: 6139: 6140: 6141: 6142: 6143: 6144: 6145: 6146: 6147: 6148: 6149: 6150: 6151: 6152: 6153: 6154: 6155: 6156: 6157: 6158: 6159: 6160: 6161: 6162: 6163: 6164: 6165: 6166: 6167: 6168: 6169: 6170: 6171: 6172: 6173: 6174: 6175: 6176: 6177: 6178: 6179: 6180: 6181: 6182: 6183: 6184: 6185: 6186: 6187: 6188: 6189: 6190: 6191: 6192: 6193: 6194: 6195: 6196: 6197: 6198: 6199: 6200: 6201: 6202: 6203: 6204: 6205: 6206: 6207: 6208: 6209: 6210: 6211: 6212: 6213: 6214: 6215: 6216: 6217: 6218: 6219: 6220: 6221: 6222: 6223: 6224: 6225: 6226: 6227: 6228: 6229: 6230: 6231: 6232: 6233: 6234: 6235: 6236: 6237: 6238: 6239: 6240: 6241: 6242: 6243: 6244: 6245: 6246: 6247: 6248: 6249: 6250: 6251: 6252: 6253: 6254: 6255: 6256: 6257: 6258: 6259: 6260: 6261: 6262: 6263: 6264: 6265: 6266: 6267: 6268: 6269: 6270: 6271: 6272: 6273: 6274: 6275: 6276: 6277: 6278: 6279: 6280: 6281: 6282: 6283: 6284: 6285: 6286: 6287: 6288: 6289: 6290: 6291: 6292: 6293: 6294: 6295: 6296: 6297: 6298: 6299: 6300: 6301: 6302: 6303: 6304: 6305: 6306: 6307: 6308: 6309: 6310: 6311: 6312: 6313: 6314: 6315: 6316: 6317: 6318: 6319: 6320: 6321: 6322: 6323: 6324: 6325: 6326: 6327: 6328: 6329: 6330: 6331: 6332: 6333: 6334: 6335: 6336: 6337: 6338: 6339: 6340: 6341: 6342: 6343: 6344: 6345: 6346: 6347: 6348: 6349: 6350: 6351: 6352: 6353: 6354: 6355: 6356: 6357: 6358: 6359: 6360: 6361: 6362: 6363: 6364: 6365: 6366: 6367: 6368: 6369: 6370: 6371: 6372: 6373: 6374: 6375: 6376: 6377: 6378: 6379: 6380: 6381: 6382: 6383: 6384: 6385: 6386: 6387: 6388: 6389: 6390: 6391: 6392: 6393: 6394: 6395: 6396: 6397: 6398: 6399: 6400: 6401: 6402: 6403: 6404: 6405: 6406: 6407: 6408: 6409: 6410: 6411: 6412: 6413: 6414: 6415: 6416: 6417: 6418: 6419: 6420: 6421: 6422: 6423: 6424: 6425: 6426: 6427: 6428: 6429: 6430: 6431: 6432: 6433: 6434: 6435: 6436: 6437: 6438: 6439: 6440: 6441: 6442: 6443: 6444: 6445: 6446: 6447: 6448: 6449: 6450: 6451: 6452: 6453: 6454: 6455: 6456: 6457: 6458: 6459: 6460: 6461: 6462: 6463: 6464: 6465: 6466: 6467: 6468: 6469: 6470: 6471: 6472: 6473: 6474: 6475: 6476: 6477: 6478: 6479: 6480: 6481: 6482: 6483: 6484: 6485: 6486: 6487: 6488: 6489: 6490: 6491: 6492: 6493: 6494: 6495: 6496: 6497: 6498: 6499: 6500: 6501: 6502: 6503: 6504: 6505: 6506: 6507: 6508: 6509: 6510: 6511: 6512: 6513: 6514: 6515: 6516: 6517: 6518: 6519: 6520: 6521: 6522: 6523: 6524: 6525: 6526: 6527: 6528: 6529: 6530: 6531: 6532: 6533: 6534: 6535: 6536: 6537: 6538: 6539: 6540: 6541: 6542: 6543: 6544: 6545: 6546: 6547: 6548: 6549: 6550: 6551: 6552: 6553: 6554: 6555: 6556: 6557: 6558: 6559: 6560: 6561: 6562: 6563: 6564: 6565: 6566: 6567: 6568: 6569: 6570: 6571: 6572: 6573: 6574: 6575: 6576: 6577: 6578: 6579: 6580: 6581: 6582: 6583: 6584: 6585: 6586: 6587: 6588: 6589: 6590: 6591: 6592: 6593: 6594: 6595: 6596: 6597: 6598: 6599: 6600: 6601: 6602: 6603: 6604: 6605: 6606: 6607: 6608: 6609: 6610: 6611: 6612: 6613: 6614: 6615: 6616: 6617: 6618: 6619: 6620: 6621: 6622: 6623: 6624: 6625: 6626: 6627: 6628: 6629: 6630: 6631: 6632: 6633: 6634: 6635: 6636: 6637: 6638: 6639: 6640: 6641: 6642: 6643: 6644: 6645: 6646: 6647: 6648: 6649: 6650: 6651: 6652: 6653: 6654: 6655: 6656: 6657: 6658: 6659: 6660: 6661: 6662: 6663: 6664: 6665: 6666: 6667: 6668: 6669: 6670: 6671: 6672: 6673: 6674: 6675: 6676: 6677: 6678: 6679: 6680: 6681: 6682: 6683: 6684: 6685: 6686: 6687: 6688: 6689: 6690: 6691: 6692: 6693: 6694: 6695: 6696: 6697: 6698: 6699: 6700: 6701: 6702: 6703: 6704: 6705: 6706: 6707: 6708: 6709: 6710: 6711: 6712: 6713: 6714: 6715: 6716: 6717: 6718: 6719: 6720: 6721: 6722: 6723: 6724: 6725: 6726: 6727: 6728: 6729: 6730: 6731: 6732: 6733: 6734: 6735: 6736: 6737: 6738: 6739: 6740: 6741: 6742: 6743: 6744: 6745: 6746: 6747: 6748: 6749: 6750: 6751: 6752: 6753: 6754: 6755: 6756: 6757: 6758: 6759: 6760: 6761: 6762: 6763: 6764: 6765: 6766: 6767: 6768: 6769: 6770: 6771: 6772: 6773: 6774: 6775: 6776: 6777: 6778: 6779: 6780: 6781: 6782: 6783: 6784: 6785: 6786: 6787: 6788: 6789: 6790: 6791: 6792: 6793: 6794: 6795: 6796: 6797: 6798: 6799: 6800: 6801: 6802: 6803: 6804: 6805: 6806: 6807: 6808: 6809: 6810: 6811: 6812: 6813: 6814: 6815: 6816: 6817: 6818: 6819: 6820: 6821: 6822: 6823: 6824: 6825: 6826: 6827: 6828: 6829: 6830: 6831: 6832: 6833: 6834: 6835: 6836: 6837: 6838: 6839: 6840: 6841: 6842: 6843: 6844: 6845: 6846: 6847: 6848: 6849: 6850: 6851: 6852: 6853: 6854: 6855: 6856: 6857: 6858: 6859: 6860: 6861: 6862: 6863: 6864: 6865: 6866: 6867: 6868: 6869: 6870: 6871: 6872: 6873: 6874: 6875: 6876: 6877: 6878: 6879: 6880: 6881: 6882: 6883: 6884: 6885: 6886: 6887: 6888: 6889: 6890: 6891: 6892: 6893: 6894: 6895: 6896: 6897: 6898: 6899: 6900: 6901: 6902: 6903: 6904: 6905: 6906: 6907: 6908: 6909: 6910: 6911: 6912: 6913: 6914: 6915: 6916: 6917: 6918: 6919: 6920: 6921: 6922: 6923: 6924: 6925: 6926: 6927: 6928: 6929: 6930: 6931: 6932: 6933: 6934: 6935: 6936: 6937: 6938: 6939: 6940: 6941: 6942: 6943: 6944: 6945: 6946: 6947: 6948: 6949: 6950: 6951: 6952: 6953: 6954: 6955: 6956: 6957: 6958: 6959: 6960: 6961: 6962: 6963: 6964: 6965: 6966: 6967: 6968: 6969: 6970: 6971: 6972: 6973: 6974: 6975: 6976: 6977: 6978: 6979: 6980: 6981: 6982: 6983: 6984: 6985: 6986: 6987: 6988: 6989: 6990: 6991: 6992: 6993: 6994: 6995: 6996: 6997: 6998: 6999: 7000: 7001: 7002: 7003: 7004: 7005: 7006: 7007: 7008: 7009: 7010: 7011: 7012: 7013: 7014: 7015: 7016: 7017: 7018: 7019: 7020: 7021: 7022: 7023: 7024: 7025: 7026: 7027: 7028: 7029: 7030: 7031: 7032: 7033: 7034: 7035: 7036: 7037: 7038: 7039: 7040: 7041: 7042: 7043: 7044: 7045: 7046: 7047: 7048: 7049: 7050: 7051: 7052: 7053: 7054: 7055: 7056: 7057: 7058: 7059: 7060: 7061: 7062: 7063: 7064: 7065: 7066: 7067: 7068: 7069: 7070: 7071: 7072: 7073: 7074: 7075: 7076: 7077: 7078: 7079: 7080: 7081: 7082: 7083: 7084: 7085: 7086: 7087: 7088: 7089: 7090: 7091: 7092: 7093: 7094: 7095: 7096: 7097: 7098: 7099: 7100: 7101: 7102: 7103: 7104: 7105: 7106: 7107: 7108: 7109: 7110: 7111: 7112: 7113: 7114: 7115: 7116: 7117: 7118: 7119: 7120: 7121: 7122: 7123: 7124: 7125: 7126: 7127: 7128: 7129: 7130: 7131: 7132: 7133: 7134: 7135: 7136: 7137: 7138: 7139: 7140: 7141: 7142: 7143: 7144: 7145: 7146: 7147: 7148: 7149: 7150: 7151: 7152: 7153: 7154: 7155: 7156: 7157: 7158: 7159: 7160: 7161: 7162: 7163: 7164: 7165: 7166: 7167: 7168: 7169: 7170: 7171: 7172: 7173: 7174: 7175: 7176: 7177: 7178: 7179: 7180: 7181: 7182: 7183: 7184: 7185: 7186: 7187: 7188: 7189: 7190: 7191: 7192: 7193: 7194: 7195: 7196: 7197: 7198: 7199: 7200: 7201: 7202: 7203: 7204: 7205: 7206: 7207: 7208: 7209: 7210: 7211: 7212: 7213: 7214: 7215: 7216: 7217: 7218: 7219: 7220: 7221: 7222: 7223: 7224: 7225: 7226: 7227: 7228: 7229: 7230: 7231: 7232: 7233: 7234: 7235: 7236: 7237: 7238: 7239: 7240: 7241: 7242: 7243: 7244: 7245: 7246: 7247: 7248: 7249: 7250: 7251: 7252: 7253: 7254: 7255: 7256: 7257: 7258: 7259: 7260: 7261: 7262: 7263: 7264: 7265: 7266: 7267: 7268: 7269: 7270: 7271: 7272: 7273: 7274: 7275: 7276: 7277: 7278: 7279: 7280: 7281: 7282: 7283: 7284: 7285: 7286: 7287: 7288: 7289: 7290: 7291: 7292: 7293: 7294: 7295: 7296: 7297: 7298: 7299: 7300: 7301: 7302: 7303: 7304: 7305: 7306: 7307: 7308: 7309: 7310: 7311: 7312: 7313: 7314: 7315: 7316: 7317: 7318: 7319: 7320: 7321: 7322: 7323: 7324: 7325: 7326: 7327: 7328: 7329: 7330: 7331: 7332: 7333: 7334: 7335: 7336: 7337: 7338: 7339: 7340: 7341: 7342: 7343: 7344: 7345: 7346: 7347: 7348: 7349: 7350: 7351: 7352: 7353: 7354: 7355: 7356: 7357: 7358: 7359: 7360: 7361: 7362: 7363: 7364: 7365: 7366: 7367: 7368: 7369: 7370: 7371: 7372: 7373: 7374: 7375: 7376: 7377: 7378: 7379: 7380: 7381: 7382: 7383: 7384: 7385: 7386: 7387: 7388: 7389: 7390: 7391: 7392: 7393: 7394: 7395: 7396: 7397: 7398: 7399: 7400: 7401: 7402: 7403: 7404: 7405: 7406: 7407: 7408: 7409: 7410: 7411: 7412: 7413: 7414: 7415: 7416: 7417: 7418: 7419: 7420: 7421: 7422: 7423: 7424: 7425: 7426: 7427: 7428: 7429: 7430: 7431: 7432: 7433: 7434: 7435: 7436: 7437: 7438: 7439: 7440: 7441: 7442: 7443: 7444: 7445: 7446: 7447: 7448: 7449: 7450: 7451: 7452: 7453: 7454: 7455: 7456: 7457: 7458: 7459: 7460: 7461: 7462: 7463: 7464: 7465: 7466: 7467: 7468: 7469: 7470: 7471: 7472: 7473: 7474: 7475: 7476: 7477: 7478: 7479: 7480: 7481: 7482: 7483: 7484: 7485: 7486: 7487: 7488: 7489: 7490: 7491: 7492: 7493: 7494: 7495: 7496: 7497: 7498: 7499: 7500: 7501: 7502: 7503: 7504: 7505: 7506: 7507: 7508: 7509: 7510: 7511: 7512: 7513: 7514: 7515: 7516: 7517: 7518: 7519: 7520: 7521: 7522: 7523: 7524: 7525: 7526: 7527: 7528: 7529: 7530: 7531: 7532: 7533: 7534: 7535: 7536: 7537: 7538: 7539: 7540: 7541: 7542: 7543: 7544: 7545: 7546: 7547: 7548: 7549: 7550: 7551: 7552: 7553: 7554: 7555: 7556: 7557: 7558: 7559: 7560: 7561: 7562: 7563: 7564: 7565: 7566: 7567: 7568: 7569: 7570: 7571: 7572: 7573: 7574: 7575: 7576: 7577: 7578: 7579: 7580: 7581: 7582: 7583: 7584: 7585: 7586: 7587: 7588: 7589: 7590: 7591: 7592: 7593: 7594: 7595: 7596: 7597: 7598: 7599: 7600: 7601: 7602: 7603: 7604: 7605: 7606: 7607: 7608: 7609: 7610: 7611: 7612: 7613: 7614: 7615: 7616: 7617: 7618: 7619: 7620: 7621: 7622: 7623: 7624: 7625: 7626: 7627: 7628: 7629: 7630: 7631: 7632: 7633: 7634: 7635: 7636: 7637: 7638: 7639: 7640: 7641: 7642: 7643: 7644: 7645: 7646: 7647: 7648: 7649: 7650: 7651: 7652: 7653: 7654: 7655: 7656: 7657: 7658: 7659: 7660: 7661: 7662: 7663: 7664: 7665: 7666: 7667: 7668: 7669: 7670: 7671: 7672: 7673: 7674: 7675: 7676: 7677: 7678: 7679: 7680: 7681: 7682: 7683: 7684: 7685: 7686: 7687: 7688: 7689: 7690: 7691: 7692: 7693: 7694: 7695: 7696: 7697: 7698: 7699: 7700: 7701: 7702: 7703: 7704: 7705: 7706: 7707: 7708: 7709: 7710: 7711: 7712: 7713: 7714: 7715: 7716: 7717: 7718: 7719: 7720: 7721: 7722: 7723: 7724: 7725: 7726: 7727: 7728: 7729: 7730: 7731: 7732: 7733: 7734: 7735: 7736: 7737: 7738: 7739: 7740: 7741: 7742: 7743: 7744: 7745: 7746: 7747: 7748: 7749: 7750: 7751: 7752: 7753: 7754: 7755: 7756: 7757: 7758: 7759: 7760: 7761: 7762: 7763: 7764: 7765: 7766: 7767: 7768: 7769: 7770: 7771: 7772: 7773: 7774: 7775: 7776: 7777: 7778: 7779: 7780: 7781: 7782: 7783: 7784: 7785: 7786: 7787: 7788: 7789: 7790: 7791: 7792: 7793: 7794: 7795: 7796: 7797: 7798: 7799: 7800: 7801: 7802: 7803: 7804: 7805: 7806: 7807: 7808: 7809: 7810: 7811: 7812: 7813: 7814: 7815: 7816: 7817: 7818: 7819: 7820: 7821: 7822: 7823: 7824: 7825: 7826: 7827: 7828: 7829: 7830: 7831: 7832: 7833: 7834: 7835: 7836: 7837: 7838: 7839: 7840: 7841: 7842: 7843: 7844: 7845: 7846: 7847: 7848: 7849: 7850: 7851: 7852: 7853: 7854: 7855: 7856: 7857: 7858: 7859: 7860: 7861: 7862: 7863: 7864: 7865: 7866: 7867: 7868: 7869: 7870: 7871: 7872: 7873: 7874: 7875: 7876: 7877: 7878: 7879: 7880: 7881: 7882: 7883: 7884: 7885: 7886: 7887: 7888: 7889: 7890: 7891: 7892: 7893: 7894: 7895: 7896: 7897: 7898: 7899: 7900: 7901: 7902: 7903: 7904: 7905: 7906: 7907: 7908: 7909: 7910: 7911: 7912: 7913: 7914: 7915: 7916: 7917: 7918: 7919: 7920: 7921: 7922: 7923: 7924: 7925: 7926: 7927: 7928: 7929: 7930: 7931: 7932: 7933: 7934: 7935: 7936: 7937: 7938: 7939: 7940: 7941: 7942: 7943: 7944: 7945: 7946: 7947: 7948: 7949: 7950: 7951: 7952: 7953: 7954: 7955: 7956: 7957: 7958: 7959: 7960: 7961: 7962: 7963: 7964: 7965: 7966: 7967: 7968: 7969: 7970: 7971: 7972: 7973: 7974: 7975: 7976: 7977: 7978: 7979: 7980: 7981: 7982: 7983: 7984: 7985: 7986: 7987: 7988: 7989: 7990: 7991: 7992: 7993: 7994: 7995: 7996: 7997: 7998: 7999: 8000: 8001: 8002: 8003: 8004: 8005: 8006: 8007: 8008: 8009: 8010: 8011: 8012: 8013: 8014: 8015: 8016: 8017: 8018: 8019: 8020: 8021: 8022: 8023: 8024: 8025: 8026: 8027: 8028: 8029: 8030: 8031: 8032: 8033: 8034: 8035: 8036: 8037: 8038: 8039: 8040: 8041: 8042: 8043: 8044: 8045: 8046: 8047: 8048: 8049: 8050: 8051: 8052: 8053: 8054: 8055: 8056: 8057: 8058: 8059: 8060: 8061: 8062: 8063: 8064: 8065: 8066: 8067: 8068: 8069: 8070: 8071: 8072: 8073: 8074: 8075: 8076: 8077: 8078: 8079: 8080: 8081: 8082: 8083: 8084: 8085: 8086: 8087: 8088: 8089: 8090: 8091: 8092: 8093: 8094: 8095: 8096: 8097: 8098: 8099: 8100: 8101: 8102: 8103: 8104: 8105: 8106: 8107: 8108: 8109: 8110: 8111: 8112: 8113: 8114: 8115: 8116: 8117: 8118: 8119: 8120: 8121: 8122: 8123: 8124: 8125: 8126: 8127: 8128: 8129: 8130: 8131: 8132: 8133: 8134: 8135: 8136: 8137: 8138: 8139: 8140: 8141: 8142: 8143: 8144: 8145: 8146: 8147: 8148: 8149: 8150: 8151: 8152: 8153: 8154: 8155: 8156: 8157: 8158: 8159: 8160: 8161: 8162: 8163: 8164: 8165: 8166: 8167: 8168: 8169: 8170: 8171: 8172: 8173: 8174: 8175: 8176: 8177: 8178: 8179: 8180: 8181: 8182: 8183: 8184: 8185: 8186: 8187: 8188: 8189: 8190: 8191: 8192: 8193: 8194: 8195: 8196: 8197: 8198: 8199: 8200: 8201: 8202: 8203: 8204: 8205: 8206: 8207: 8208: 8209: 8210: 8211: 8212: 8213: 8214: 8215: 8216: 8217: 8218: 8219: 8220: 8221: 8222: 8223: 8224: 8225: 8226: 8227: 8228: 8229: 8230: 8231: 8232: 8233: 8234: 8235: 8236: 8237: 8238: 8239: 8240: 8241: 8242: 8243: 8244: 8245: 8246: 8247: 8248: 8249: 8250: 8251: 8252: 8253: 8254: 8255: 8256: 8257: 8258: 8259: 8260: 8261: 8262: 8263: 8264: 8265: 8266: 8267: 8268: 8269: 8270: 8271: 8272: 8273: 8274: 8275: 8276: 8277: 8278: 8279: 8280: 8281: 8282: 8283: 8284: 8285: 8286: 8287: 8288: 8289: 8290: 8291: 8292: 8293: 8294: 8295: 8296: 8297: 8298: 8299: 8300: 8301: 8302: 8303: 8304: 8305: 8306: 8307: 8308: 8309: 8310: 8311: 8312: 8313: 8314: 8315: 8316: 8317: 8318: 8319: 8320: 8321: 8322: 8323: 8324: 8325: 8326: 8327: 8328: 8329: 8330: 8331: 8332: 8333: 8334: 8335: 8336: 8337: 8338: 8339: 8340: 8341: 8342: 8343: 8344: 8345: 8346: 8347: 8348: 8349: 8350: 8351: 8352: 8353: 8354: 8355: 8356: 8357: 8358: 8359: 8360: 8361: 8362: 8363: 8364: 8365: 8366: 8367: 8368: 8369: 8370: 8371: 8372: 8373: 8374: 8375: 8376: 8377: 8378: 8379: 8380: 8381: 8382: 8383: 8384: 8385: 8386: 8387: 8388: 8389: 8390: 8391: 8392: 8393: 8394: 8395: 8396: 8397: 8398: 8399: 8400: 8401: 8402: 8403: 8404: 8405: 8406: 8407: 8408: 8409: 8410: 8411: 8412: 8413: 8414: 8415: 8416: 8417: 8418: 8419: 8420: 8421: 8422: 8423: 8424: 8425: 8426: 8427: 8428: 8429: 8430: 8431: 8432: 8433: 8434: 8435: 8436: 8437: 8438: 8439: 8440: 8441: 8442: 8443: 8444: 8445: 8446: 8447: 8448: 8449: 8450: 8451: 8452: 8453: 8454: 8455: 8456: 8457: 8458: 8459: 8460: 8461: 8462: 8463: 8464: 8465: 8466: 8467: 8468: 8469: 8470: 8471: 8472: 8473: 8474: 8475: 8476: 8477: 8478: 8479: 8480: 8481: 8482: 8483: 8484: 8485: 8486: 8487: 8488: 8489: 8490: 8491: 8492: 8493: 8494: 8495: 8496: 8497: 8498: 8499: 8500: 8501: 8502: 8503: 8504: 8505: 8506: 8507: 8508: 8509: 8510: 8511: 8512: 8513: 8514: 8515: 8516: 8517: 8518: 8519: 8520: 8521: 8522: 8523: 8524: 8525: 8526: 8527: 8528: 8529: 8530: 8531: 8532: 8533: 8534: 8535: 8536: 8537: 8538: 8539: 8540: 8541: 8542: 8543: 8544: 8545: 8546: 8547: 8548: 8549: 8550: 8551: 8552: 8553: 8554: 8555: 8556: 8557: 8558: 8559: 8560: 8561: 8562: 8563: 8564: 8565: 8566: 8567: 8568: 8569: 8570: 8571: 8572: 8573: 8574: 8575: 8576: 8577: 8578: 8579: 8580: 8581: 8582: 8583: 8584: 8585: 8586: 8587: 8588: 8589: 8590: 8591: 8592: 8593: 8594: 8595: 8596: 8597: 8598: 8599: 8600: 8601: 8602: 8603: 8604: 8605: 8606: 8607: 8608: 8609: 8610: 8611: 8612: 8613: 8614: 8615: 8616: 8617: 8618: 8619: 8620: 8621: 8622: 8623: 8624: 8625: 8626: 8627: 8628: 8629: 8630: 8631: 8632: 8633: 8634: 8635: 8636: 8637: 8638: 8639: 8640: 8641: 8642: 8643: 8644: 8645: 8646: 8647: 8648: 8649: 8650: 8651: 8652: 8653: 8654: 8655: 8656: 8657: 8658: 8659: 8660: 8661: 8662: 8663: 8664: 8665: 8666: 8667: 8668: 8669: 8670: 8671: 8672: 8673: 8674: 8675: 8676: 8677: 8678: 8679: 8680: 8681: 8682: 8683: 8684: 8685: 8686: 8687: 8688: 8689: 8690: 8691: 8692: 8693: 8694: 8695: 8696: 8697: 8698: 8699: 8700: 8701: 8702: 8703: 8704: 8705: 8706: 8707: 8708: 8709: 8710: 8711: 8712: 8713: 8714: 8715: 8716: 8717: 8718: 8719: 8720: 8721: 8722: 8723: 8724: 8725: 8726: 8727: 8728: 8729: 8730: 8731: 8732: 8733: 8734: 8735: 8736: 8737: 8738: 8739: 8740: 8741: 8742: 8743: 8744: 8745: 8746: 8747: 8748: 8749: 8750: 8751: 8752: 8753: 8754: 8755: 8756: 8757: 8758: 8759: 8760: 8761: 8762: 8763: 8764: 8765: 8766: 8767: 8768: 8769: 8770: 8771: 8772: 8773: 8774: 8775: 8776: 8777: 8778: 8779: 8780: 8781: 8782: 8783: 8784: 8785: 8786: 8787: 8788: 8789: 8790: 8791: 8792: 8793: 8794: 8795: 8796: 8797: 8798: 8799: 8800: 8801: 8802: 8803: 8804: 8805: 8806: 8807: 8808: 8809: 8810: 8811: 8812: 8813: 8814: 8815: 8816: 8817: 8818: 8819: 8820: 8821: 8822: 8823: 8824: 8825: 8826: 8827: 8828: 8829: 8830: 8831: 8832: 8833: 8834: 8835: 8836: 8837: 8838: 8839: 8840: 8841: 8842: 8843: 8844: 8845: 8846: 8847: 8848: 8849: 8850: 8851: 8852: 8853: 8854: 8855: 8856: 8857: 8858: 8859: 8860: 8861: 8862: 8863: 8864: 8865: 8866: 8867: 8868: 8869: 8870: 8871: 8872: 8873: 8874: 8875: 8876: 8877: 8878: 8879: 8880: 8881: 8882: 8883: 8884: 8885: 8886: 8887: 8888: 8889: 8890: 8891: 8892: 8893: 8894: 8895: 8896: 8897: 8898: 8899: 8900: 8901: 8902: 8903: 8904: 8905: 8906: 8907: 8908: 8909: 8910: 8911: 8912: 8913: 8914: 8915: 8916: 8917: 8918: 8919: 8920: 8921: 8922: 8923: 8924: 8925: 8926: 8927: 8928: 8929: 8930: 8931: 8932: 8933: 8934: 8935: 8936: 8937: 8938: 8939: 8940: 8941: 8942: 8943: 8944: 8945: 8946: 8947: 8948: 8949: 8950: 8951: 8952: 8953: 8954: 8955: 8956: 8957: 8958: 8959: 8960: 8961: 8962: 8963: 8964: 8965: 8966: 8967: 8968: 8969: 8970: 8971: 8972: 8973: 8974: 8975: 8976: 8977: 8978: 8979: 8980: 8981: 8982: 8983: 8984: 8985: 8986: 8987: 8988: 8989: 8990: 8991: 8992: 8993: 8994: 8995: 8996: 8997: 8998: 8999: 9000: 9001: 9002: 9003: 9004: 9005: 9006: 9007: 9008: 9009: 9010: 9011: 9012: 9013: 9014: 9015: 9016: 9017: 9018: 9019: 9020: 9021: 9022: 9023: 9024: 9025: 9026: 9027: 9028: 9029: 9030: 9031: 9032: 9033: 9034: 9035: 9036: 9037: 9038: 9039: 9040: 9041: 9042: 9043: 9044: 9045: 9046: 9047: 9048: 9049: 9050: 9051: 9052: 9053: 9054: 9055: 9056: 9057: 9058: 9059: 9060: 9061: 9062: 9063: 9064: 9065: 9066: 9067: 9068: 9069: 9070: 9071: 9072: 9073: 9074: 9075: 9076: 9077: 9078: 9079: 9080: 9081: 9082: 9083: 9084: 9085: 9086: 9087: 9088: 9089: 9090: 9091: 9092: 9093: 9094: 9095: 9096: 9097: 9098: 9099: 9100: 9101: 9102: 9103: 9104: 9105: 9106: 9107: 9108: 9109: 9110: 9111: 9112: 9113: 9114: 9115: 9116: 9117: 9118: 9119: 9120: 9121: 9122: 9123: 9124: 9125: 9126: 9127: 9128: 9129: 9130: 9131: 9132: 9133: 9134: 9135: 9136: 9137: 9138: 9139: 9140: 9141: 9142: 9143: 9144: 9145: 9146: 9147: 9148: 9149: 9150: 9151: 9152: 9153: 9154: 9155: 9156: 9157: 9158: 9159: 9160: 9161: 9162: 9163: 9164: 9165: 9166: 9167: 9168: 9169: 9170: 9171: 9172: 9173: 9174: 9175: 9176: 9177: 9178: 9179: 9180: 9181: 9182: 9183: 9184: 9185: 9186: 9187: 9188: 9189: 9190: 9191: 9192: 9193: 9194: 9195: 9196: 9197: 9198: 9199: 9200: 9201: 9202: 9203: 9204: 9205: 9206: 9207: 9208: 9209: 9210: 9211: 9212: 9213: 9214: 9215: 9216: 9217: 9218: 9219: 9220: 9221: 9222: 9223: 9224: 9225: 9226: 9227: 9228: 9229: 9230: 9231: 9232: 9233: 9234: 9235: 9236: 9237: 9238: 9239: 9240: 9241: 9242: 9243: 9244: 9245: 9246: 9247: 9248: 9249: 9250: 9251: 9252: 9253: 9254: 9255: 9256: 9257: 9258: 9259: 9260: 9261: 9262: 9263: 9264: 9265: 9266: 9267: 9268: 9269: 9270: 9271: 9272: 9273: 9274: 9275: 9276: 9277: 9278: 9279: 9280: 9281: 9282: 9283: 9284: 9285: 9286: 9287: 9288: 9289: 9290: 9291: 9292: 9293: 9294: 9295: 9296: 9297: 9298: 9299: 9300: 9301: 9302: 9303: 9304: 9305: 9306: 9307: 9308: 9309: 9310: 9311: 9312: 9313: 9314: 9315: 9316: 9317: 9318: 9319: 9320: 9321: 9322: 9323: 9324: 9325: 9326: 9327: 9328: 9329: 9330: 9331: 9332: 9333: 9334: 9335: 9336: 9337: 9338: 9339: 9340: 9341: 9342: 9343: 9344: 9345: 9346: 9347: 9348: 9349: 9350: 9351: 9352: 9353: 9354: 9355: 9356: 9357: 9358: 9359: 9360: 9361: 9362: 9363: 9364: 9365: 9366: 9367: 9368: 9369: 9370: 9371: 9372: 9373: 9374: 9375: 9376: 9377: 9378: 9379: 9380: 9381: 9382: 9383: 9384: 9385: 9386: 9387: 9388: 9389: 9390: 9391: 9392: 9393: 9394: 9395: 9396: 9397: 9398: 9399: 9400: 9401: 9402: 9403: 9404: 9405: 9406: 9407: 9408: 9409: 9410: 9411: 9412: 9413: 9414: 9415: 9416: 9417: 9418: 9419: 9420: 9421: 9422: 9423: 9424: 9425: 9426: 9427: 9428: 9429: 9430: 9431: 9432: 9433: 9434: 9435: 9436: 9437: 9438: 9439: 9440: 9441: 9442: 9443: 9444: 9445: 9446: 9447: 9448: 9449: 9450: 9451: 9452: 9453: 9454: 9455: 9456: 9457: 9458: 9459: 9460: 9461: 9462: 9463: 9464: 9465: 9466: 9467: 9468: 9469: 9470: 9471: 9472: 9473: 9474: 9475: 9476: 9477: 9478: 9479: 9480: 9481: 9482: 9483: 9484: 9485: 9486: 9487: 9488: 9489: 9490: 9491: 9492: 9493: 9494: 9495: 9496: 9497: 9498: 9499: 9500: 9501: 9502: 9503: 9504: 9505: 9506: 9507: 9508: 9509: 9510: 9511: 9512: 9513: 9514: 9515: 9516: 9517: 9518: 9519: 9520: 9521: 9522: 9523: 9524: 9525: 9526: 9527: 9528: 9529: 9530: 9531: 9532: 9533: 9534: 9535: 9536: 9537: 9538: 9539: 9540: 9541: 9542: 9543: 9544: 9545: 9546: 9547: 9548: 9549: 9550: 9551: 9552: 9553: 9554: 9555: 9556: 9557: 9558: 9559: 9560: 9561: 9562: 9563: 9564: 9565: 9566: 9567: 9568: 9569: 9570: 9571: 9572: 9573: 9574: 9575: 9576: 9577: 9578: 9579: 9580: 9581: 9582: 9583: 9584: 9585: 9586: 9587: 9588: 9589: 9590: 9591: 9592: 9593: 9594: 9595: 9596: 9597: 9598: 9599: 9600: 9601: 9602: 9603: 9604: 9605: 9606: 9607: 9608: 9609: 9610: 9611: 9612: 9613: 9614: 9615: 9616: 9617: 9618: 9619: 9620: 9621: 9622: 9623: 9624: 9625: 9626: 9627: 9628: 9629: 9630: 9631: 9632: 9633: 9634: 9635: 9636: 9637: 9638: 9639: 9640: 9641: 9642: 9643: 9644: 9645: 9646: 9647: 9648: 9649: 9650: 9651: 9652: 9653: 9654: 9655: 9656: 9657: 9658: 9659: 9660: 9661: 9662: 9663: 9664: 9665: 9666: 9667: 9668: 9669: 9670: 9671: 9672: 9673: 9674: 9675: 9676: 9677: 9678: 9679: 9680: 9681: 9682: 9683: 9684: 9685: 9686: 9687: 9688: 9689: 9690: 9691: 9692: 9693: 9694: 9695: 9696: 9697: 9698: 9699: 9700: 9701: 9702: 9703: 9704: 9705: 9706: 9707: 9708: 9709: 9710: 9711: 9712: 9713: 9714: 9715: 9716: 9717: 9718: 9719: 9720: 9721: 9722: 9723: 9724: 9725: 9726: 9727: 9728: 9729: 9730: 9731: 9732: 9733: 9734: 9735: 9736: 9737: 9738: 9739: 9740: 9741: 9742: 9743: 9744: 9745: 9746: 9747: 9748: 9749: 9750: 9751: 9752: 9753: 9754: 9755: 9756: 9757: 9758: 9759: 9760: 9761: 9762: 9763: 9764: 9765: 9766: 9767: 9768: 9769: 9770: 9771: 9772: 9773: 9774: 9775: 9776: 9777: 9778: 9779: 9780: 9781: 9782: 9783: 9784: 9785: 9786: 9787: 9788: 9789: 9790: 9791: 9792: 9793: 9794: 9795: 9796: 9797: 9798: 9799: 9800: 9801: 9802: 9803: 9804: 9805: 9806: 9807: 9808: 9809: 9810: 9811: 9812: 9813: 9814: 9815: 9816: 9817: 9818: 9819: 9820: 9821: 9822: 9823: 9824: 9825: 9826: 9827: 9828: 9829: 9830: 9831: 9832: 9833: 9834: 9835: 9836: 9837: 9838: 9839: 9840: 9841: 9842: 9843: 9844: 9845: 9846: 9847: 9848: 9849: 9850: 9851: 9852: 9853: 9854: 9855: 9856: 9857: 9858: 9859: 9860: 9861: 9862: 9863: 9864: 9865: 9866: 9867: 9868: 9869: 9870: 9871: 9872: 9873: 9874: 9875: 9876: 9877: 9878: 9879: 9880: 9881: 9882: 9883: 9884: 9885: 9886: 9887: 9888: 9889: 9890: 9891: 9892: 9893: 9894: 9895: 9896: 9897: 9898: 9899: 9900: 9901: 9902: 9903: 9904: 9905: 9906: 9907: 9908: 9909: 9910: 9911: 9912: 9913: 9914: 9915: 9916: 9917: 9918: 9919: 9920: 9921: 9922: 9923: 9924: 9925: 9926: 9927: 9928: 9929: 9930: 9931: 9932: 9933: 9934: 9935: 9936: 9937: 9938: 9939: 9940: 9941: 9942: 9943: 9944: 9945: 9946: 9947: 9948: 9949: 9950: 9951: 9952: 9953: 9954: 9955: 9956: 9957: 9958: 9959: 9960: 9961: 9962: 9963: 9964: 9965: 9966: 9967: 9968: 9969: 9970: 9971: 9972: 9973: 9974: 9975: 9976: 9977: 9978: 9979: 9980: 9981: 9982: 9983: 9984: 9985: 9986: 9987: 9988: 9989: 9990: 9991: 9992: 9993: 9994: 9995: 9996: 9997: 9998: 9999: 10000: 10001: 10002: 10003: 10004: 10005: 10006: 10007: 10008: 10009: 10010: 10011: 10012: 10013: 10014: 10015: 10016: 10017: 10018: 10019: 10020: 10021: 10022: 10023: 10024: 10025: 10026: 10027: 10028: 10029: 10030: 10031: 10032: 10033: 10034: 10035: 10036: 10037: 10038: 10039: 10040: 10041: 10042: 10043: 10044: 10045: 10046: 10047: 10048: 10049: 10050: 10051: 10052: 10053: 10054: 10055: 10056: 10057: 10058: 10059: 10060: 10061: 10062: 10063: 10064: 10065: 10066: 10067: 10068: 10069: 10070: 10071: 10072: 10073: 10074: 10075: 10076: 10077: 10078: 10079: 10080: 10081: 10082: 10083: 10084: 10085: 10086: 10087: 10088: 10089: 10090: 10091: 10092: 10093: 10094: 10095: 10096: 10097: 10098: 10099: 10100: 10101: 10102: 10103: 10104: 10105: 10106: 10107: 10108: 10109: 10110: 10111: 10112: 10113: 10114: 10115: 10116: 10117: 10118: 10119: 10120: 10121: 10122: 10123: 10124: 10125: 10126: 10127: 10128: 10129: 10130: 10131: 10132: 10133: 10134: 10135: 10136: 10137: 10138: 10139: 10140: 10141: 10142: 10143: 10144: 10145: 10146: 10147: 10148: 10149: 10150: 10151: 10152: 10153: 10154: 10155: 10156: 10157: 10158: 10159: 10160: 10161: 10162: 10163: 10164: 10165: 10166: 10167: 10168: 10169: 10170: 10171: 10172: 10173: 10174: 10175: 10176: 10177: 10178: 10179: 10180: 10181: 10182: 10183: 10184: 10185: 10186: 10187: 10188: 10189: 10190: 10191: 10192: 10193: 10194: 10195: 10196: 10197: 10198: 10199: 10200: 10201: 10202: 10203: 10204: 10205: 10206: 10207: 10208: 10209: 10210: 10211: 10212: 10213: 10214: 10215: 10216: 10217: 10218: 10219: 10220: 10221: 10222: 10223: 10224: 10225: 10226: 10227: 10228: 10229: 10230: 10231: 10232: 10233: 10234: 10235: 10236: 10237: 10238: 10239: 10240: 10241: 10242: 10243: 10244: 10245: 10246: 10247: 10248: 10249: 10250: 10251: 10252: 10253: 10254: 10255: 10256: 10257: 10258: 10259: 10260: 10261: 10262: 10263: 10264: 10265: 10266: 10267: 10268: 10269: 10270: 10271: 10272: 10273: 10274: 10275: 10276: 10277: 10278: 10279: 10280: 10281: 10282: 10283: 10284: 10285: 10286: 10287: 10288: 10289: 10290: 10291: 10292: 10293: 10294: 10295: 10296: 10297: 10298: 10299: 10300: 10301: 10302: 10303: 10304: 10305: 10306: 10307: 10308: 10309: 10310: 10311: 10312: 10313: 10314: 10315: 10316: 10317: 10318: 10319: 10320: 10321: 10322: 10323: 10324: 10325: 10326: 10327: 10328: 10329: 10330: 10331: 10332: 10333: 10334: 10335: 10336: 10337: 10338: 10339: 10340: 10341: 10342: 10343: 10344: 10345: 10346: 10347: 10348: 10349: 10350: 10351: 10352: 10353: 10354: 10355: 10356: 10357: 10358: 10359: 10360: 10361: 10362: 10363: 10364: 10365: 10366: 10367: 10368: 10369: 10370: 10371: 10372: 10373: 10374: 10375: 10376: 10377: 10378: 10379: 10380: 10381: 10382: 10383: 10384: 10385: 10386: 10387: 10388: 10389: 10390: 10391: 10392: 10393: 10394: 10395: 10396: 10397: 10398: 10399: 10400: 10401: 10402: 10403: 10404: 10405: 10406: 10407: 10408: 10409: 10410: 10411: 10412: 10413: 10414: 10415: 10416: 10417: 10418: 10419: 10420: 10421: 10422: 10423: 10424: 10425: 10426: 10427: 10428: 10429: 10430: 10431: 10432: 10433: 10434: 10435: 10436: 10437: 10438: 10439: 10440: 10441: 10442: 10443: 10444: 10445: 10446: 10447: 10448: 10449: 10450: 10451: 10452: 10453: 10454: 10455: 10456: 10457: 10458: 10459: 10460: 10461: 10462: 10463: 10464: 10465: 10466: 10467: 10468: 10469: 10470: 10471: 10472: 10473: 10474: 10475: 10476: 10477: 10478: 10479: 10480: 10481: 10482: 10483: 10484: 10485: 10486: 10487: 10488: 10489: 10490: 10491: 10492: 10493: 10494: 10495: 10496: 10497: 10498: 10499: 10500: 10501: 10502: 10503: 10504: 10505: 10506: 10507: 10508: 10509: 10510: 10511: 10512: 10513: 10514: 10515: 10516: 10517: 10518: 10519: 10520: 10521: 10522: 10523: 10524: 10525: 10526: 10527: 10528: 10529: 10530: 10531: 10532: 10533: 10534: 10535: 10536: 10537: 10538: 10539: 10540: 10541: 10542: 10543: 10544: 10545: 10546: 10547: 10548: 10549: 10550: 10551: 10552: 10553: 10554: 10555: 10556: 10557: 10558: 10559: 10560: 10561: 10562: 10563: 10564: 10565: 10566: 10567: 10568: 10569: 10570: 10571: 10572: 10573: 10574: 10575: 10576: 10577: 10578: 10579: 10580: 10581: 10582: 10583: 10584: 10585: 10586: 10587: 10588: 10589: 10590: 10591: 10592: 10593: 10594: 10595: 10596: 10597: 10598: 10599: 10600: 10601: 10602: 10603: 10604: 10605: 10606: 10607: 10608: 10609: 10610: 10611: 10612: 10613: 10614: 10615: 10616: 10617: 10618: 10619: 10620: 10621: 10622: 10623: 10624: 10625: 10626: 10627: 10628: 10629: 10630: 10631: 10632: 10633: 10634: 10635: 10636: 10637: 10638: 10639: 10640: 10641: 10642: 10643: 10644: 10645: 10646: 10647: 10648: 10649: 10650: 10651: 10652: 10653: 10654: 10655: 10656: 10657: 10658: 10659: 10660: 10661: 10662: 10663: 10664: 10665: 10666: 10667: 10668: 10669: 10670: 10671: 10672: 10673: 10674: 10675: 10676: 10677: 10678: 10679: 10680: 10681: 10682: 10683: 10684: 10685: 10686: 10687: 10688: 10689: 10690: 10691: 10692: 10693: 10694: 10695: 10696: 10697: 10698: 10699: 10700: 10701: 10702: 10703: 10704: 10705: 10706: 10707: 10708: 10709: 10710: 10711: 10712: 10713: 10714: 10715: 10716: 10717: 10718: 10719: 10720: 10721: 10722: 10723: 10724: 10725: 10726: 10727: 10728: 10729: 10730: 10731: 10732: 10733: 10734: 10735: 10736: 10737: 10738: 10739: 10740: 10741: 10742: 10743: 10744: 10745: 10746: 10747: 10748: 10749: 10750: 10751: 10752: 10753: 10754: 10755: 10756: 10757: 10758: 10759: 10760: 10761: 10762: 10763: 10764: 10765: 10766: 10767: 10768: 10769: 10770: 10771: 10772: 10773: 10774: 10775: 10776: 10777: 10778: 10779: 10780: 10781: 10782: 10783: 10784: 10785: 10786: 10787: 10788: 10789: 10790: 10791: 10792: 10793: 10794: 10795: 10796: 10797: 10798: 10799: 10800: 10801: 10802: 10803: 10804: 10805: 10806: 10807: 10808: 10809: 10810: 10811: 10812: 10813: 10814: 10815: 10816: 10817: 10818: 10819: 10820: 10821: 10822: 10823: 10824: 10825: 10826: 10827: 10828: 10829: 10830: 10831: 10832: 10833: 10834: 10835: 10836: 10837: 10838: 10839: 10840: 10841: 10842: 10843: 10844: 10845: 10846: 10847: 10848: 10849: 10850: 10851: 10852: 10853: 10854: 10855: 10856: 10857: 10858: 10859: 10860: 10861: 10862: 10863: 10864: 10865: 10866: 10867: 10868: 10869: 10870: 10871: 10872: 10873: 10874: 10875: 10876: 10877: 10878: 10879: 10880: 10881: 10882: 10883: 10884: 10885: 10886: 10887: 10888: 10889: 10890: 10891: 10892: 10893: 10894: 10895: 10896: 10897: 10898: 10899: 10900: 10901: 10902: 10903: 10904: 10905: 10906: 10907: 10908: 10909: 10910: 10911: 10912: 10913: 10914: 10915: 10916: 10917: 10918: 10919: 10920: 10921: 10922: 10923: 10924: 10925: 10926: 10927: 10928: 10929: 10930: 10931: 10932: 10933: 10934: 10935: 10936: 10937: 10938: 10939: 10940: 10941: 10942: 10943: 10944: 10945: 10946: 10947: 10948: 10949: 10950: 10951: 10952: 10953: 10954: 10955: 10956: 10957: 10958: 10959: 10960: 10961: 10962: 10963: 10964: 10965: 10966: 10967: 10968: 10969: 10970: 10971: 10972: 10973: 10974: 10975: 10976: 10977: 10978: 10979: 10980: 10981: 10982: 10983: 10984: 10985: 10986: 10987: 10988: 10989: 10990: 10991: 10992: 10993: 10994: 10995: 10996: 10997: 10998: 10999: 11000: 11001: 11002: 11003: 11004: 11005: 11006: 11007: 11008: 11009: 11010: 11011: 11012: 11013: 11014: 11015: 11016: 11017: 11018: 11019: 11020: 11021: 11022: 11023: 11024: 11025: 11026: 11027: 11028: 11029: 11030: 11031: 11032: 11033: 11034: 11035: 11036: 11037: 11038: 11039: 11040: 11041: 11042: 11043: 11044: 11045: 11046: 11047: 11048: 11049: 11050: 11051: 11052: 11053: 11054: 11055: 11056: 11057: 11058: 11059: 11060: 11061: 11062: 11063: 11064: 11065: 11066: 11067: 11068: 11069: 11070: 11071: 11072: 11073: 11074: 11075: 11076: 11077: 11078: 11079: 11080: 11081: 11082: 11083: 11084: 11085: 11086: 11087: 11088: 11089: 11090: 11091: 11092: 11093: 11094: 11095: 11096: 11097: 11098: 11099: 11100: 11101: 11102: 11103: 11104: 11105: 11106: 11107: 11108: 11109: 11110: 11111: 11112: 11113: 11114: 11115: 11116: 11117: 11118: 11119: 11120: 11121: 11122: 11123: 11124: 11125: 11126: 11127: 11128: 11129: 11130: 11131: 11132: 11133: 11134: 11135: 11136: 11137: 11138: 11139: 11140: 11141: 11142: 11143: 11144: 11145: 11146: 11147: 11148: 11149: 11150: 11151: 11152: 11153: 11154: 11155: 11156: 11157: 11158: 11159: 11160: 11161: 11162: 11163: 11164: 11165: 11166: 11167: 11168: 11169: 11170: 11171: 11172: 11173: 11174: 11175: 11176: 11177: 11178: 11179: 11180: 11181: 11182: 11183: 11184: 11185: 11186: 11187: 11188: 11189: 11190: 11191: 11192: 11193: 11194: 11195: 11196: 11197: 11198: 11199: 11200: 11201: 11202: 11203: 11204: 11205: 11206: 11207: 11208: 11209: 11210: 11211: 11212: 11213: 11214: 11215: 11216: 11217: 11218: 11219: 11220: 11221: 11222: 11223: 11224: 11225: 11226: 11227: 11228: 11229: 11230: 11231: 11232: 11233: 11234: 11235: 11236: 11237: 11238: 11239: 11240: 11241: 11242: 11243: 11244: 11245: 11246: 11247: 11248: 11249: 11250: 11251: 11252: 11253: 11254: 11255: 11256: 11257: 11258: 11259: 11260: 11261: 11262: 11263: 11264: 11265: 11266: 11267: 11268: 11269: 11270: 11271: 11272: 11273: 11274: 11275: 11276: 11277: 11278: 11279: 11280: 11281: 11282: 11283: 11284: 11285: 11286: 11287: 11288: 11289: 11290: 11291: 11292: 11293: 11294: 11295: 11296: 11297: 11298: 11299: 11300: 11301: 11302: 11303: 11304: 11305: 11306: 11307: 11308: 11309: 11310: 11311: 11312: 11313: 11314: 11315: 11316: 11317: 11318: 11319: 11320: 11321: 11322: 11323: 11324: 11325: 11326: 11327: 11328: 11329: 11330: 11331: 11332: 11333: 11334: 11335: 11336: 11337: 11338: 11339: 11340: 11341: 11342: 11343: 11344: 11345: 11346: 11347: 11348: 11349: 11350: 11351: 11352: 11353: 11354: 11355: 11356: 11357: 11358: 11359: 11360: 11361: 11362: 11363: 11364: 11365: 11366: 11367: 11368: 11369: 11370: 11371: 11372: 11373: 11374: 11375: 11376: 11377: 11378: 11379: 11380: 11381: 11382: 11383: 11384: 11385: 11386: 11387: 11388: 11389: 11390: 11391: 11392: 11393: 11394: 11395: 11396: 11397: 11398: 11399: 11400: 11401: 11402: 11403: 11404: 11405: 11406: 11407: 11408: 11409: 11410: 11411: 11412: 11413: 11414: 11415: 11416: 11417: 11418: 11419: 11420: 11421: 11422: 11423: 11424: 11425: 11426: 11427: 11428: 11429: 11430: 11431: 11432: 11433: 11434: 11435: 11436: 11437: 11438: 11439: 11440: 11441: 11442: 11443: 11444: 11445: 11446: 11447: 11448: 11449: 11450: 11451: 11452: 11453: 11454: 11455: 11456: 11457: 11458: 11459: 11460: 11461: 11462: 11463: 11464: 11465: 11466: 11467: 11468: 11469: 11470: 11471: 11472: 11473: 11474: 11475: 11476: 11477: 11478: 11479: 11480: 11481: 11482: 11483: 11484: 11485: 11486: 11487: 11488: 11489: 11490: 11491: 11492: 11493: 11494: 11495: 11496: 11497: 11498: 11499: 11500: 11501: 11502: 11503: 11504: 11505: 11506: 11507: 11508: 11509: 11510: 11511: 11512: 11513: 11514: 11515: 11516: 11517: 11518: 11519: 11520: 11521: 11522: 11523: 11524: 11525: 11526: 11527: 11528: 11529: 11530: 11531: 11532: 11533: 11534: 11535: 11536: 11537: 11538: 11539: 11540: 11541: 11542: 11543: 11544: 11545: 11546: 11547: 11548: 11549: 11550: 11551: 11552: 11553: 11554: 11555: 11556: 11557: 11558: 11559: 11560: 11561: 11562: 11563: 11564: 11565: 11566: 11567: 11568: 11569: 11570: 11571: 11572: 11573: 11574: 11575: 11576: 11577: 11578: 11579: 11580: 11581: 11582: 11583: 11584: 11585: 11586: 11587: 11588: 11589: 11590: 11591: 11592: 11593: 11594: 11595: 11596: 11597: 11598: 11599: 11600: 11601: 11602: 11603: 11604: 11605: 11606: 11607: 11608: 11609: 11610: 11611: 11612: 11613: 11614: 11615: 11616: 11617: 11618: 11619: 11620: 11621: 11622: 11623: 11624: 11625: 11626: 11627: 11628: 11629: 11630: 11631: 11632: 11633: 11634: 11635: 11636: 11637: 11638: 11639: 11640: 11641: 11642: 11643: 11644: 11645: 11646: 11647: 11648: 11649: 11650: 11651: 11652: 11653: 11654: 11655: 11656: 11657: 11658: 11659: 11660: 11661: 11662: 11663: 11664: 11665: 11666: 11667: 11668: 11669: 11670: 11671: 11672: 11673: 11674: 11675: 11676: 11677: 11678: 11679: 11680: 11681: 11682: 11683: 11684: 11685: 11686: 11687: 11688: 11689: 11690: 11691: 11692: 11693: 11694: 11695: 11696: 11697: 11698: 11699: 11700: 11701: 11702: 11703: 11704: 11705: 11706: 11707: 11708: 11709: 11710: 11711: 11712: 11713: 11714: 11715: 11716: 11717: 11718: 11719: 11720: 11721: 11722: 11723: 11724: 11725: 11726: 11727: 11728: 11729: 11730: 11731: 11732: 11733: 11734: 11735: 11736: 11737: 11738: 11739: 11740: 11741: 11742: 11743: 11744: 11745: 11746: 11747: 11748: 11749: 11750: 11751: 11752: 11753: 11754: 11755: 11756: 11757: 11758: 11759: 11760: 11761: 11762: 11763: 11764: 11765: 11766: 11767: 11768: 11769: 11770: 11771: 11772: 11773: 11774: 11775: 11776: 11777: 11778: 11779: 11780: 11781: 11782: 11783: 11784: 11785: 11786: 11787: 11788: 11789: 11790: 11791: 11792: 11793: 11794: 11795: 11796: 11797: 11798: 11799: 11800: 11801: 11802: 11803: 11804: 11805: 11806: 11807: 11808: 11809: 11810: 11811: 11812: 11813: 11814: 11815: 11816: 11817: 11818: 11819: 11820: 11821: 11822: 11823: 11824: 11825: 11826: 11827: 11828: 11829: 11830: 11831: 11832: 11833: 11834: 11835: 11836: 11837: 11838: 11839: 11840: 11841: 11842: 11843: 11844: 11845: 11846: 11847: 11848: 11849: 11850: 11851: 11852: 11853: 11854: 11855: 11856: 11857: 11858: 11859: 11860: 11861: 11862: 11863: 11864: 11865: 11866: 11867: 11868: 11869: 11870: 11871: 11872: 11873: 11874: 11875: 11876: 11877: 11878: 11879: 11880: 11881: 11882: 11883: 11884: 11885: 11886: 11887: 11888: 11889: 11890: 11891: 11892: 11893: 11894: 11895: 11896: 11897: 11898: 11899: 11900: 11901: 11902: 11903: 11904: 11905: 11906: 11907: 11908: 11909: 11910: 11911: 11912: 11913: 11914: 11915: 11916: 11917: 11918: 11919: 11920: 11921: 11922: 11923: 11924: 11925: 11926: 11927: 11928: 11929: 11930: 11931: 11932: 11933: 11934: 11935: 11936: 11937: 11938: 11939: 11940: 11941: 11942: 11943: 11944: 11945: 11946: 11947: 11948: 11949: 11950: 11951: 11952: 11953: 11954: 11955: 11956: 11957: 11958: 11959: 11960: 11961: 11962: 11963: 11964: 11965: 11966: 11967: 11968: 11969: 11970: 11971: 11972: 11973: 11974: 11975: 11976: 11977: 11978: 11979: 11980: 11981: 11982: 11983: 11984: 11985: 11986: 11987: 11988: 11989: 11990: 11991: 11992: 11993: 11994: 11995: 11996: 11997: 11998: 11999: 12000: 12001: 12002: 12003: 12004: 12005: 12006: 12007: 12008: 12009: 12010: 12011: 12012: 12013: 12014: 12015: 12016: 12017: 12018: 12019: 12020: 12021: 12022: 12023: 12024: 12025: 12026: 12027: 12028: 12029: 12030: 12031: 12032: 12033: 12034: 12035: 12036: 12037: 12038: 12039: 12040: 12041: 12042: 12043: 12044: 12045: 12046: 12047: 12048: 12049: 12050: 12051: 12052: 12053: 12054: 12055: 12056: 12057: 12058: 12059: 12060: 12061: 12062: 12063: 12064: 12065: 12066: 12067: 12068: 12069: 12070: 12071: 12072: 12073: 12074: 12075: 12076: 12077: 12078: 12079: 12080: 12081: 12082: 12083: 12084: 12085: 12086: 12087: 12088: 12089: 12090: 12091: 12092: 12093: 12094: 12095: 12096: 12097: 12098: 12099: 12100: 12101: 12102: 12103: 12104: 12105: 12106: 12107: 12108: 12109: 12110: 12111: 12112: 12113: 12114: 12115: 12116: 12117: 12118: 12119: 12120: 12121: 12122: 12123: 12124: 12125: 12126: 12127: 12128: 12129: 12130: 12131: 12132: 12133: 12134: 12135: 12136: 12137: 12138: 12139: 12140: 12141: 12142: 12143: 12144: 12145: 12146: 12147: 12148: 12149: 12150: 12151: 12152: 12153: 12154: 12155: 12156: 12157: 12158: 12159: 12160: 12161: 12162: 12163: 12164: 12165: 12166: 12167: 12168: 12169: 12170: 12171: 12172: 12173: 12174: 12175: 12176: 12177: 12178: 12179: 12180: 12181: 12182: 12183: 12184: 12185: 12186: 12187: 12188: 12189: 12190: 12191: 12192: 12193: 12194: 12195: 12196: 12197: 12198: 12199: 12200: 12201: 12202: 12203: 12204: 12205: 12206: 12207: 12208: 12209: 12210: 12211: 12212: 12213: 12214: 12215: 12216: 12217: 12218: 12219: 12220: 12221: 12222: 12223: 12224: 12225: 12226: 12227: 12228: 12229: 12230: 12231: 12232: 12233: 12234: 12235: 12236: 12237: 12238: 12239: 12240: 12241: 12242: 12243: 12244: 12245: 12246: 12247: 12248: 12249: 12250: 12251: 12252: 12253: 12254: 12255: 12256: 12257: 12258: 12259: 12260: 12261: 12262: 12263: 12264: 12265: 12266: 12267: 12268: 12269: 12270: 12271: 12272: 12273: 12274: 12275: 12276: 12277: 12278: 12279: 12280: 12281: 12282: 12283: 12284: 12285: 12286: 12287: 12288: 12289: 12290: 12291: 12292: 12293: 12294: 12295: 12296: 12297: 12298: 12299: 12300: 12301: 12302: 12303: 12304: 12305: 12306: 12307: 12308: 12309: 12310: 12311: 12312: 12313: 12314: 12315: 12316: 12317: 12318: 12319: 12320: 12321: 12322: 12323: 12324: 12325: 12326: 12327: 12328: 12329: 12330: 12331: 12332: 12333: 12334: 12335: 12336: 12337: 12338: 12339: 12340: 12341: 12342: 12343: 12344: 12345: 12346: 12347: 12348: 12349: 12350: 12351: 12352: 12353: 12354: 12355: 12356: 12357: 12358: 12359: 12360: 12361: 12362: 12363: 12364: 12365: 12366: 12367: 12368: 12369: 12370: 12371: 12372: 12373: 12374: 12375: 12376: 12377: 12378: 12379: 12380: 12381: 12382: 12383: 12384: 12385: 12386: 12387: 12388: 12389: 12390: 12391: 12392: 12393: 12394: 12395: 12396: 12397: 12398: 12399: 12400: 12401: 12402: 12403: 12404: 12405: 12406: 12407: 12408: 12409: 12410: 12411: 12412: 12413: 12414: 12415: 12416: 12417: 12418: 12419: 12420: 12421: 12422: 12423: 12424: 12425: 12426: 12427: 12428: 12429: 12430: 12431: 12432: 12433: 12434: 12435: 12436: 12437: 12438: 12439: 12440: 12441: 12442: 12443: 12444: 12445: 12446: 12447: 12448: 12449: 12450: 12451: 12452: 12453: 12454: 12455: 12456: 12457: 12458: 12459: 12460: 12461: 12462: 12463: 12464: 12465: 12466: 12467: 12468: 12469: 12470: 12471: 12472: 12473: 12474: 12475: 12476: 12477: 12478: 12479: 12480: 12481: 12482: 12483: 12484: 12485: 12486: 12487: 12488: 12489: 12490: 12491: 12492: 12493: 12494: 12495: 12496: 12497: 12498: 12499: 12500: 12501: 12502: 12503: 12504: 12505: 12506: 12507: 12508: 12509: 12510: 12511: 12512: 12513: 12514: 12515: 12516: 12517: 12518: 12519: 12520: 12521: 12522: 12523: 12524: 12525: 12526: 12527: 12528: 12529: 12530: 12531: 12532: 12533: 12534: 12535: 12536: 12537: 12538: 12539: 12540: 12541: 12542: 12543: 12544: 12545: 12546: 12547: 12548: 12549: 12550: 12551: 12552: 12553: 12554: 12555: 12556: 12557: 12558: 12559: 12560: 12561: 12562: 12563: 12564: 12565: 12566: 12567: 12568: 12569: 12570: 12571: 12572: 12573: 12574: 12575: 12576: 12577: 12578: 12579: 12580: 12581: 12582: 12583: 12584: 12585: 12586: 12587: 12588: 12589: 12590: 12591: 12592: 12593: 12594: 12595: 12596: 12597: 12598: 12599: 12600: 12601: 12602: 12603: 12604: 12605: 12606: 12607: 12608: 12609: 12610: 12611: 12612: 12613: 12614: 12615: 12616: 12617: 12618: 12619: 12620: 12621: 12622: 12623: 12624: 12625: 12626: 12627: 12628: 12629: 12630: 12631: 12632: 12633: 12634: 12635: 12636: 12637: 12638: 12639: 12640: 12641: 12642: 12643: 12644: 12645: 12646: 12647: 12648: 12649: 12650: 12651: 12652: 12653: 12654: 12655: 12656: 12657: 12658: 12659: 12660: 12661: 12662: 12663: 12664: 12665: 12666: 12667: 12668: 12669: 12670: 12671: 12672: 12673: 12674: 12675: 12676: 12677: 12678: 12679: 12680: 12681: 12682: 12683: 12684: 12685: 12686: 12687: 12688: 12689: 12690: 12691: 12692: 12693: 12694: 12695: 12696: 12697: 12698: 12699: 12700: 12701: 12702: 12703: 12704: 12705: 12706: 12707: 12708: 12709: 12710: 12711: 12712: 12713: 12714: 12715: 12716: 12717: 12718: 12719: 12720: 12721: 12722: 12723: 12724: 12725: 12726: 12727: 12728: 12729: 12730: 12731: 12732: 12733: 12734: 12735: 12736: 12737: 12738: 12739: 12740: 12741: 12742: 12743: 12744: 12745: 12746: 12747: 12748: 12749: 12750: 12751: 12752: 12753: 12754: 12755: 12756: 12757: 12758: 12759: 12760: 12761: 12762: 12763: 12764: 12765: 12766: 12767: 12768: 12769: 12770: 12771: 12772: 12773: 12774: 12775: 12776: 12777: 12778: 12779: 12780: 12781: 12782: 12783: 12784: 12785: 12786: 12787: 12788: 12789: 12790: 12791: 12792: 12793: 12794: 12795: 12796: 12797: 12798: 12799: 12800: 12801: 12802: 12803: 12804: 12805: 12806: 12807: 12808: 12809: 12810: 12811: 12812: 12813: 12814: 12815: 12816: 12817: 12818: 12819: 12820: 12821: 12822: 12823: 12824: 12825: 12826: 12827: 12828: 12829: 12830: 12831: 12832: 12833: 12834: 12835: 12836: 12837: 12838: 12839: 12840: 12841: 12842: 12843: 12844: 12845: 12846: 12847: 12848: 12849: 12850: 12851: 12852: 12853: 12854: 12855: 12856: 12857: 12858: 12859: 12860: 12861: 12862: 12863: 12864: 12865: 12866: 12867: 12868: 12869: 12870: 12871: 12872: 12873: 12874: 12875: 12876: 12877: 12878: 12879: 12880: 12881: 12882: 12883: 12884: 12885: 12886: 12887: 12888: 12889: 12890: 12891: 12892: 12893: 12894: 12895: 12896: 12897: 12898: 12899: 12900: 12901: 12902: 12903: 12904: 12905: 12906: 12907: 12908: 12909: 12910: 12911: 12912: 12913: 12914: 12915: 12916: 12917: 12918: 12919: 12920: 12921: 12922: 12923: 12924: 12925: 12926: 12927: 12928: 12929: 12930: 12931: 12932: 12933: 12934: 12935: 12936: 12937: 12938: 12939: 12940: 12941: 12942: 12943: 12944: 12945: 12946: 12947: 12948: 12949: 12950: 12951: 12952: 12953: 12954: 12955: 12956: 12957: 12958: 12959: 12960: 12961: 12962: 12963: 12964: 12965: 12966: 12967: 12968: 12969: 12970: 12971: 12972: 12973: 12974: 12975: 12976: 12977: 12978: 12979: 12980: 12981: 12982: 12983: 12984: 12985: 12986: 12987: 12988: 12989: 12990: 12991: 12992: 12993: 12994: 12995: 12996: 12997: 12998: 12999: 13000: 13001: 13002: 13003: 13004: 13005: 13006: 13007: 13008: 13009: 13010: 13011: 13012: 13013: 13014: 13015: 13016: 13017: 13018: 13019: 13020: 13021: 13022: 13023: 13024: 13025: 13026: 13027: 13028: 13029: 13030: 13031: 13032: 13033: 13034: 13035: 13036: 13037: 13038: 13039: 13040: 13041: 13042: 13043: 13044: 13045: 13046: 13047: 13048: 13049: 13050: 13051: 13052: 13053: 13054: 13055: 13056: 13057: 13058: 13059: 13060: 13061: 13062: 13063: 13064: 13065: 13066: 13067: 13068: 13069: 13070: 13071: 13072: 13073: 13074: 13075: 13076: 13077: 13078: 13079: 13080: 13081: 13082: 13083: 13084: 13085: 13086: 13087: 13088: 13089: 13090: 13091: 13092: 13093: 13094: 13095: 13096: 13097: 13098: 13099: 13100: 13101: 13102: 13103: 13104: 13105: 13106: 13107: 13108: 13109: 13110: 13111: 13112: 13113: 13114: 13115: 13116: 13117: 13118: 13119: 13120: 13121: 13122: 13123: 13124: 13125: 13126: 13127: 13128: 13129: 13130: 13131: 13132: 13133: 13134: 13135: 13136: 13137: 13138: 13139: 13140: 13141: 13142: 13143: 13144: 13145: 13146: 13147: 13148: 13149: 13150: 13151: 13152: 13153: 13154: 13155: 13156: 13157: 13158: 13159: 13160: 13161: 13162: 13163: 13164: 13165: 13166: 13167: 13168: 13169: 13170: 13171: 13172: 13173: 13174: 13175: 13176: 13177: 13178: 13179: 13180: 13181: 13182: 13183: 13184: 13185: 13186: 13187: 13188: 13189: 13190: 13191: 13192: 13193: 13194: 13195: 13196: 13197: 13198: 13199: 13200: 13201: 13202: 13203: 13204: 13205: 13206: 13207: 13208: 13209: 13210: 13211: 13212: 13213: 13214: 13215: 13216: 13217: 13218: 13219: 13220: 13221: 13222: 13223: 13224: 13225: 13226: 13227: 13228: 13229: 13230: 13231: 13232: 13233: 13234: 13235: 13236: 13237: 13238: 13239: 13240: 13241: 13242: 13243: 13244: 13245: 13246: 13247: 13248: 13249: 13250: 13251: 13252: 13253: 13254: 13255: 13256: 13257: 13258: 13259: 13260: 13261: 13262: 13263: 13264: 13265: 13266: 13267: 13268: 13269: 13270: 13271: 13272: 13273: 13274: 13275: 13276: 13277: 13278: 13279: 13280: 13281: 13282: 13283: 13284: 13285: 13286: 13287: 13288: 13289: 13290: 13291: 13292: 13293: 13294: 13295: 13296: 13297: 13298: 13299: 13300: 13301: 13302: 13303: 13304: 13305: 13306: 13307: 13308: 13309: 13310: 13311: 13312: 13313: 13314: 13315: 13316: 13317: 13318: 13319: 13320: 13321: 13322: 13323: 13324: 13325: 13326: 13327: 13328: 13329: 13330: 13331: 13332: 13333: 13334: 13335: 13336: 13337: 13338: 13339: 13340: 13341: 13342: 13343: 13344: 13345: 13346: 13347: 13348: 13349: 13350: 13351: 13352: 13353: 13354: 13355: 13356: 13357: 13358: 13359: 13360: 13361: 13362: 13363: 13364: 13365: 13366: 13367: 13368: 13369: 13370: 13371: 13372: 13373: 13374: 13375: 13376: 13377: 13378: 13379: 13380: 13381: 13382: 13383: 13384: 13385: 13386: 13387: 13388: 13389: 13390: 13391: 13392: 13393: 13394: 13395: 13396: 13397: 13398: 13399: 13400: 13401: 13402: 13403: 13404: 13405: 13406: 13407: 13408: 13409: 13410: 13411: 13412: 13413: 13414: 13415: 13416: 13417: 13418: 13419: 13420: 13421: 13422: 13423: 13424: 13425: 13426: 13427: 13428: 13429: 13430: 13431: 13432: 13433: 13434: 13435: 13436: 13437: 13438: 13439: 13440: 13441: 13442: 13443: 13444: 13445: 13446: 13447: 13448: 13449: 13450: 13451: 13452: 13453: 13454: 13455: 13456: 13457: 13458: 13459: 13460: 13461: 13462: 13463: 13464: 13465: 13466: 13467: 13468: 13469: 13470: 13471: 13472: 13473: 13474: 13475: 13476: 13477: 13478: 13479: 13480: 13481: 13482: 13483: 13484: 13485: 13486: 13487: 13488: 13489: 13490: 13491: 13492: 13493: 13494: 13495: 13496: 13497: 13498: 13499: 13500: 13501: 13502: 13503: 13504: 13505: 13506: 13507: 13508: 13509: 13510: 13511: 13512: 13513: 13514: 13515: 13516: 13517: 13518: 13519: 13520: 13521: 13522: 13523: 13524: 13525: 13526: 13527: 13528: 13529: 13530: 13531: 13532: 13533: 13534: 13535: 13536: 13537: 13538: 13539: 13540: 13541: 13542: 13543: 13544: 13545: 13546: 13547: 13548: 13549: 13550: 13551: 13552: 13553: 13554: 13555: 13556: 13557: 13558: 13559: 13560: 13561: 13562: 13563: 13564: 13565: 13566: 13567: 13568: 13569: 13570: 13571: 13572: 13573: 13574: 13575: 13576: 13577: 13578: 13579: 13580: 13581: 13582: 13583: 13584: 13585: 13586: 13587: 13588: 13589: 13590: 13591: 13592: 13593: 13594: 13595: 13596: 13597: 13598: 13599: 13600: 13601: 13602: 13603: 13604: 13605: 13606: 13607: 13608: 13609: 13610: 13611: 13612: 13613: 13614: 13615: 13616: 13617: 13618: 13619: 13620: 13621: 13622: 13623: 13624: 13625: 13626: 13627: 13628: 13629: 13630: 13631: 13632: 13633: 13634: 13635: 13636: 13637: 13638: 13639: 13640: 13641: 13642: 13643: 13644: 13645: 13646: 13647: 13648: 13649: 13650: 13651: 13652: 13653: 13654: 13655: 13656: 13657: 13658: 13659: 13660: 13661: 13662: 13663: 13664: 13665: 13666: 13667: 13668: 13669: 13670: 13671: 13672: 13673: 13674: 13675: 13676: 13677: 13678: 13679: 13680: 13681: 13682: 13683: 13684: 13685: 13686: 13687: 13688: 13689: 13690: 13691: 13692: 13693: 13694: 13695: 13696: 13697: 13698: 13699: 13700: 13701: 13702: 13703: 13704: 13705: 13706: 13707: 13708: 13709: 13710: 13711: 13712: 13713: 13714: 13715: 13716: 13717: 13718: 13719: 13720: 13721: 13722: 13723: 13724: 13725: 13726: 13727: 13728: 13729: 13730: 13731: 13732: 13733: 13734: 13735: 13736: 13737: 13738: 13739: 13740: 13741: 13742: 13743: 13744: 13745: 13746: 13747: 13748: 13749: 13750: 13751: 13752: 13753: 13754: 13755: 13756: 13757: 13758: 13759: 13760: 13761: 13762: 13763: 13764: 13765: 13766: 13767: 13768: 13769: 13770: 13771: 13772: 13773: 13774: 13775: 13776: 13777: 13778: 13779: 13780: 13781: 13782: 13783: 13784: 13785: 13786: 13787: 13788: 13789: 13790: 13791: 13792: 13793: 13794: 13795: 13796: 13797: 13798: 13799: 13800: 13801: 13802: 13803: 13804: 13805: 13806: 13807: 13808: 13809: 13810: 13811: 13812: 13813: 13814: 13815: 13816: 13817: 13818: 13819: 13820: 13821: 13822: 13823: 13824: 13825: 13826: 13827: 13828: 13829: 13830: 13831: 13832: 13833: 13834: 13835: 13836: 13837: 13838: 13839: 13840: 13841: 13842: 13843: 13844: 13845: 13846: 13847: 13848: 13849: 13850: 13851: 13852: 13853: 13854: 13855: 13856: 13857: 13858: 13859: 13860: 13861: 13862: 13863: 13864: 13865: 13866: 13867: 13868: 13869: 13870: 13871: 13872: 13873: 13874: 13875: 13876: 13877: 13878: 13879: 13880: 13881: 13882: 13883: 13884: 13885: 13886: 13887: 13888: 13889: 13890: 13891: 13892: 13893: 13894: 13895: 13896: 13897: 13898: 13899: 13900: 13901: 13902: 13903: 13904: 13905: 13906: 13907: 13908: 13909: 13910: 13911: 13912: 13913: 13914: 13915: 13916: 13917: 13918: 13919: 13920: 13921: 13922: 13923: 13924: 13925: 13926: 13927: 13928: 13929: 13930: 13931: 13932: 13933: 13934: 13935: 13936: 13937: 13938: 13939: 13940: 13941: 13942: 13943: 13944: 13945: 13946: 13947: 13948: 13949: 13950: 13951: 13952: 13953: 13954: 13955: 13956: 13957: 13958: 13959: 13960: 13961: 13962: 13963: 13964: 13965: 13966: 13967: 13968: 13969: 13970: 13971: 13972: 13973: 13974: 13975: 13976: 13977: 13978: 13979: 13980: 13981: 13982: 13983: 13984: 13985: 13986: 13987: 13988: 13989: 13990: 13991: 13992: 13993: 13994: 13995: 13996: 13997: 13998: 13999: 14000: 14001: 14002: 14003: 14004: 14005: 14006: 14007: 14008: 14009: 14010: 14011: 14012: 14013: 14014: 14015: 14016: 14017: 14018: 14019: 14020: 14021: 14022: 14023: 14024: 14025: 14026: 14027: 14028: 14029: 14030: 14031: 14032: 14033: 14034: 14035: 14036: 14037: 14038: 14039: 14040: 14041: 14042: 14043: 14044: 14045: 14046: 14047: 14048: 14049: 14050: 14051: 14052: 14053: 14054: 14055: 14056: 14057: 14058: 14059: 14060: 14061: 14062: 14063: 14064: 14065: 14066: 14067: 14068: 14069: 14070: 14071: 14072: 14073: 14074: 14075: 14076: 14077: 14078: 14079: 14080: 14081: 14082: 14083: 14084: 14085: 14086: 14087: 14088: 14089: 14090: 14091: 14092: 14093: 14094: 14095: 14096: 14097: 14098: 14099: 14100: 14101: 14102: 14103: 14104: 14105: 14106: 14107: 14108: 14109: 14110: 14111: 14112: 14113: 14114: 14115: 14116: 14117: 14118: 14119: 14120: 14121: 14122: 14123: 14124: 14125: 14126: 14127: 14128: 14129: 14130: 14131: 14132: 14133: 14134: 14135: 14136: 14137: 14138: 14139: 14140: 14141: 14142: 14143: 14144: 14145: 14146: 14147: 14148: 14149: 14150: 14151: 14152: 14153: 14154: 14155: 14156: 14157: 14158: 14159: 14160: 14161: 14162: 14163: 14164: 14165: 14166: 14167: 14168: 14169: 14170: 14171: 14172: 14173: 14174: 14175: 14176: 14177: 14178: 14179: 14180: 14181: 14182: 14183: 14184: 14185: 14186: 14187: 14188: 14189: 14190: 14191: 14192: 14193: 14194: 14195: 14196: 14197: 14198: 14199: 14200: 14201: 14202: 14203: 14204: 14205: 14206: 14207: 14208: 14209: 14210: 14211: 14212: 14213: 14214: 14215: 14216: 14217: 14218: 14219: 14220: 14221: 14222: 14223: 14224: 14225: 14226: 14227: 14228: 14229: 14230: 14231: 14232: 14233: 14234: 14235: 14236: 14237: 14238: 14239: 14240: 14241: 14242: 14243: 14244: 14245: 14246: 14247: 14248: 14249: 14250: 14251: 14252: 14253: 14254: 14255: 14256: 14257: 14258: 14259: 14260: 14261: 14262: 14263: 14264: 14265: 14266: 14267: 14268: 14269: 14270: 14271: 14272: 14273: 14274: 14275: 14276: 14277: 14278: 14279: 14280: 14281: 14282: 14283: 14284: 14285: 14286: 14287: 14288: 14289: 14290: 14291: 14292: 14293: 14294: 14295: 14296: 14297: 14298: 14299: 14300: 14301: 14302: 14303: 14304: 14305: 14306: 14307: 14308: 14309: 14310: 14311: 14312: 14313: 14314: 14315: 14316: 14317: 14318: 14319: 14320: 14321: 14322: 14323: 14324: 14325: 14326: 14327: 14328: 14329: 14330: 14331: 14332: 14333: 14334: 14335: 14336: 14337: 14338: 14339: 14340: 14341: 14342: 14343: 14344: 14345: 14346: 14347: 14348: 14349: 14350: 14351: 14352: 14353: 14354: 14355: 14356: 14357: 14358: 14359: 14360: 14361: 14362: 14363: 14364: 14365: 14366: 14367: 14368: 14369: 14370: 14371: 14372: 14373: 14374: 14375: 14376: 14377: 14378: 14379: 14380: 14381: 14382: 14383: 14384: 14385: 14386: 14387: 14388: 14389: 14390: 14391: 14392: 14393: 14394: 14395: 14396: 14397: 14398: 14399: 14400: 14401: 14402: 14403: 14404: 14405: 14406: 14407: 14408: 14409: 14410: 14411: 14412: 14413: 14414: 14415: 14416: 14417: 14418: 14419: 14420: 14421: 14422: 14423: 14424: 14425: 14426: 14427: 14428: 14429: 14430: 14431: 14432: 14433: 14434: 14435: 14436: 14437: 14438: 14439: 14440: 14441: 14442: 14443: 14444: 14445: 14446: 14447: 14448: 14449: 14450: 14451: 14452: 14453: 14454: 14455: 14456: 14457: 14458: 14459: 14460: 14461: 14462: 14463: 14464: 14465: 14466: 14467: 14468: 14469: 14470: 14471: 14472: 14473: 14474: 14475: 14476: 14477: 14478: 14479: 14480: 14481: 14482: 14483: 14484: 14485: 14486: 14487: 14488: 14489: 14490: 14491: 14492: 14493: 14494: 14495: 14496: 14497: 14498: 14499: 14500: 14501: 14502: 14503: 14504: 14505: 14506: 14507: 14508: 14509: 14510: 14511: 14512: 14513: 14514: 14515: 14516: 14517: 14518: 14519: 14520: 14521: 14522: 14523: 14524: 14525: 14526: 14527: 14528: 14529: 14530: 14531: 14532: 14533: 14534: 14535: 14536: 14537: 14538: 14539: 14540: 14541: 14542: 14543: 14544: 14545: 14546: 14547: 14548: 14549: 14550: 14551: 14552: 14553: 14554: 14555: 14556: 14557: 14558: 14559: 14560: 14561: 14562: 14563: 14564: 14565: 14566: 14567: 14568: 14569: 14570: 14571: 14572: 14573: 14574: 14575: 14576: 14577: 14578: 14579: 14580: 14581: 14582: 14583: 14584: 14585: 14586: 14587: 14588: 14589: 14590: 14591: 14592: 14593: 14594: 14595: 14596: 14597: 14598: 14599: 14600: 14601: 14602: 14603: 14604: 14605: 14606: 14607: 14608: 14609: 14610: 14611: 14612: 14613: 14614: 14615: 14616: 14617: 14618: 14619: 14620: 14621: 14622: 14623: 14624: 14625: 14626: 14627: 14628: 14629: 14630: 14631: 14632: 14633: 14634: 14635: 14636: 14637: 14638: 14639: 14640: 14641: 14642: 14643: 14644: 14645: 14646: 14647: 14648: 14649: 14650: 14651: 14652: 14653: 14654: 14655: 14656: 14657: 14658: 14659: 14660: 14661: 14662: 14663: 14664: 14665: 14666: 14667: 14668: 14669: 14670: 14671: 14672: 14673: 14674: 14675: 14676: 14677: 14678: 14679: 14680: 14681: 14682: 14683: 14684: 14685: 14686: 14687: 14688: 14689: 14690: 14691: 14692: 14693: 14694: 14695: 14696: 14697: 14698: 14699: 14700: 14701: 14702: 14703: 14704: 14705: 14706: 14707: 14708: 14709: 14710: 14711: 14712: 14713: 14714: 14715: 14716: 14717: 14718: 14719: 14720: 14721: 14722: 14723: 14724: 14725: 14726: 14727: 14728: 14729: 14730: 14731: 14732: 14733: 14734: 14735: 14736: 14737: 14738: 14739: 14740: 14741: 14742: 14743: 14744: 14745: 14746: 14747: 14748: 14749: 14750: 14751: 14752: 14753: 14754: 14755: 14756: 14757: 14758: 14759: 14760: 14761: 14762: 14763: 14764: 14765: 14766: 14767: 14768: 14769: 14770: 14771: 14772: 14773: 14774: 14775: 14776: 14777: 14778: 14779: 14780: 14781: 14782: 14783: 14784: 14785: 14786: 14787: 14788: 14789: 14790: 14791: 14792: 14793: 14794: 14795: 14796: 14797: 14798: 14799: 14800: 14801: 14802: 14803: 14804: 14805: 14806: 14807: 14808: 14809: 14810: 14811: 14812: 14813: 14814: 14815: 14816: 14817: 14818: 14819: 14820: 14821: 14822: 14823: 14824: 14825: 14826: 14827: 14828: 14829: 14830: 14831: 14832: 14833: 14834: 14835: 14836: 14837: 14838: 14839: 14840: 14841: 14842: 14843: 14844: 14845: 14846: 14847: 14848: 14849: 14850: 14851: 14852: 14853: 14854: 14855: 14856: 14857: 14858: 14859: 14860: 14861: 14862: 14863: 14864: 14865: 14866: 14867: 14868: 14869: 14870: 14871: 14872: 14873: 14874: 14875: 14876: 14877: 14878: 14879: 14880: 14881: 14882: 14883: 14884: 14885: 14886: 14887: 14888: 14889: 14890: 14891: 14892: 14893: 14894: 14895: 14896: 14897: 14898: 14899: 14900: 14901: 14902: 14903: 14904: 14905: 14906: 14907: 14908: 14909: 14910: 14911: 14912: 14913: 14914: 14915: 14916: 14917: 14918: 14919: 14920: 14921: 14922: 14923: 14924: 14925: 14926: 14927: 14928: 14929: 14930: 14931: 14932: 14933: 14934: 14935: 14936: 14937: 14938: 14939: 14940: 14941: 14942: 14943: 14944: 14945: 14946: 14947: 14948: 14949: 14950: 14951: 14952: 14953: 14954: 14955: 14956: 14957: 14958: 14959: 14960: 14961: 14962: 14963: 14964: 14965: 14966: 14967: 14968: 14969: 14970: 14971: 14972: 14973: 14974: 14975: 14976: 14977: 14978: 14979: 14980: 14981: 14982: 14983: 14984: 14985: 14986: 14987: 14988: 14989: 14990: 14991: 14992: 14993: 14994: 14995: 14996: 14997: 14998: 14999: 15000: 15001: 15002: 15003: 15004: 15005: 15006: 15007: 15008: 15009: 15010: 15011: 15012: 15013: 15014: 15015: 15016: 15017: 15018: 15019: 15020: 15021: 15022: 15023: 15024: 15025: 15026: 15027: 15028: 15029: 15030: 15031: 15032: 15033: 15034: 15035: 15036: 15037: 15038: 15039: 15040: 15041: 15042: 15043: 15044: 15045: 15046: 15047: 15048: 15049: 15050: 15051: 15052: 15053: 15054: 15055: 15056: 15057: 15058: 15059: 15060: 15061: 15062: 15063: 15064: 15065: 15066: 15067: 15068: 15069: 15070: 15071: 15072: 15073: 15074: 15075: 15076: 15077: 15078: 15079: 15080: 15081: 15082: 15083: 15084: 15085: 15086: 15087: 15088: 15089: 15090: 15091: 15092: 15093: 15094: 15095: 15096: 15097: 15098: 15099: 15100: 15101: 15102: 15103: 15104: 15105: 15106: 15107: 15108: 15109: 15110: 15111: 15112: 15113: 15114: 15115: 15116: 15117: 15118: 15119: 15120: 15121: 15122: 15123: 15124: 15125: 15126: 15127: 15128: 15129: 15130: 15131: 15132: 15133: 15134: 15135: 15136: 15137: 15138: 15139: 15140: 15141: 15142: 15143: 15144: 15145: 15146: 15147: 15148: 15149: 15150: 15151: 15152: 15153: 15154: 15155: 15156: 15157: 15158: 15159: 15160: 15161: 15162: 15163: 15164: 15165: 15166: 15167: 15168: 15169: 15170: 15171: 15172: 15173: 15174: 15175: 15176: 15177: 15178: 15179: 15180: 15181: 15182: 15183: 15184: 15185: 15186: 15187: 15188: 15189: 15190: 15191: 15192: 15193: 15194: 15195: 15196: 15197: 15198: 15199: 15200: 15201: 15202: 15203: 15204: 15205: 15206: 15207: 15208: 15209: 15210: 15211: 15212: 15213: 15214: 15215: 15216: 15217: 15218: 15219: 15220: 15221: 15222: 15223: 15224: 15225: 15226: 15227: 15228: 15229: 15230: 15231: 15232: 15233: 15234: 15235: 15236: 15237: 15238: 15239: 15240: 15241: 15242: 15243: 15244: 15245: 15246: 15247: 15248: 15249: 15250: 15251: 15252: 15253: 15254: 15255: 15256: 15257: 15258: 15259: 15260: 15261: 15262: 15263: 15264: 15265: 15266: 15267: 15268: 15269: 15270: 15271: 15272: 15273: 15274: 15275: 15276: 15277: 15278: 15279: 15280: 15281: 15282: 15283: 15284: 15285: 15286: 15287: 15288: 15289: 15290: 15291: 15292: 15293: 15294: 15295: 15296: 15297: 15298: 15299: 15300: 15301: 15302: 15303: 15304: 15305: 15306: 15307: 15308: 15309: 15310: 15311: 15312: 15313: 15314: 15315: 15316: 15317: 15318: 15319: 15320: 15321: 15322: 15323: 15324: 15325: 15326: 15327: 15328: 15329: 15330: 15331: 15332: 15333: 15334: 15335: 15336: 15337: 15338: 15339: 15340: 15341: 15342: 15343: 15344: 15345: 15346: 15347: 15348: 15349: 15350: 15351: 15352: 15353: 15354: 15355: 15356: 15357: 15358: 15359: 15360: 15361: 15362: 15363: 15364: 15365: 15366: 15367: 15368: 15369: 15370: 15371: 15372: 15373: 15374: 15375: 15376: 15377: 15378: 15379: 15380: 15381: 15382: 15383: 15384: 15385: 15386: 15387: 15388: 15389: 15390: 15391: 15392: 15393: 15394: 15395: 15396: 15397: 15398: 15399: 15400: 15401: 15402: 15403: 15404: 15405: 15406: 15407: 15408: 15409: 15410: 15411: 15412: 15413: 15414: 15415: 15416: 15417: 15418: 15419: 15420: 15421: 15422: 15423: 15424: 15425: 15426: 15427: 15428: 15429: 15430: 15431: 15432: 15433: 15434: 15435: 15436: 15437: 15438: 15439: 15440: 15441: 15442: 15443: 15444: 15445: 15446: 15447: 15448: 15449: 15450: 15451: 15452: 15453: 15454: 15455: 15456: 15457: 15458: 15459: 15460: 15461: 15462: 15463: 15464: 15465: 15466: 15467: 15468: 15469: 15470: 15471: 15472: 15473: 15474: 15475: 15476: 15477: 15478: 15479: 15480: 15481: 15482: 15483: 15484: 15485: 15486: 15487: 15488: 15489: 15490: 15491: 15492: 15493: 15494: 15495: 15496: 15497: 15498: 15499: 15500: 15501: 15502: 15503: 15504: 15505: 15506: 15507: 15508: 15509: 15510: 15511: 15512: 15513: 15514: 15515: 15516: 15517: 15518: 15519: 15520: 15521: 15522: 15523: 15524: 15525: 15526: 15527: 15528: 15529: 15530: 15531: 15532: 15533: 15534: 15535: 15536: 15537: 15538: 15539: 15540: 15541: 15542: 15543: 15544: 15545: 15546: 15547: 15548: 15549: 15550: 15551: 15552: 15553: 15554: 15555: 15556: 15557: 15558: 15559: 15560: 15561: 15562: 15563: 15564: 15565: 15566: 15567: 15568: 15569: 15570: 15571: 15572: 15573: 15574: 15575: 15576: 15577: 15578: 15579: 15580: 15581: 15582: 15583: 15584: 15585: 15586: 15587: 15588: 15589: 15590: 15591: 15592: 15593: 15594: 15595: 15596: 15597: 15598: 15599: 15600: 15601: 15602: 15603: 15604: 15605: 15606: 15607: 15608: 15609: 15610: 15611: 15612: 15613: 15614: 15615: 15616: 15617: 15618: 15619: 15620: 15621: 15622: 15623: 15624: 15625: 15626: 15627: 15628: 15629: 15630: 15631: 15632: 15633: 15634: 15635: 15636: 15637: 15638: 15639: 15640: 15641: 15642: 15643: 15644: 15645: 15646: 15647: 15648: 15649: 15650: 15651: 15652: 15653: 15654: 15655: 15656: 15657: 15658: 15659: 15660: 15661: 15662: 15663: 15664: 15665: 15666: 15667: 15668: 15669: 15670: 15671: 15672: 15673: 15674: 15675: 15676: 15677: 15678: 15679: 15680: 15681: 15682: 15683: 15684: 15685: 15686: 15687: 15688: 15689: 15690: 15691: 15692: 15693: 15694: 15695: 15696: 15697: 15698: 15699: 15700: 15701: 15702: 15703: 15704: 15705: 15706: 15707: 15708: 15709: 15710: 15711: 15712: 15713: 15714: 15715: 15716: 15717: 15718: 15719: 15720: 15721: 15722: 15723: 15724: 15725: 15726: 15727: 15728: 15729: 15730: 15731: 15732: 15733: 15734: 15735: 15736: 15737: 15738: 15739: 15740: 15741: 15742: 15743: 15744: 15745: 15746: 15747: 15748: 15749: 15750: 15751: 15752: 15753: 15754: 15755: 15756: 15757: 15758: 15759: 15760: 15761: 15762: 15763: 15764: 15765: 15766: 15767: 15768: 15769: 15770: 15771: 15772: 15773: 15774: 15775: 15776: 15777: 15778: 15779: 15780: 15781: 15782: 15783: 15784: 15785: 15786: 15787: 15788: 15789: 15790: 15791: 15792: 15793: 15794: 15795: 15796: 15797: 15798: 15799: 15800: 15801: 15802: 15803: 15804: 15805: 15806: 15807: 15808: 15809: 15810: 15811: 15812: 15813: 15814: 15815: 15816: 15817: 15818: 15819: 15820: 15821: 15822: 15823: 15824: 15825: 15826: 15827: 15828: 15829: 15830: 15831: 15832: 15833: 15834: 15835: 15836: 15837: 15838: 15839: 15840: 15841: 15842: 15843: 15844: 15845: 15846: 15847: 15848: 15849: 15850: 15851: 15852: 15853: 15854: 15855: 15856: 15857: 15858: 15859: 15860: 15861: 15862: 15863: 15864: 15865: 15866: 15867: 15868: 15869: 15870: 15871: 15872: 15873: 15874: 15875: 15876: 15877: 15878: 15879: 15880: 15881: 15882: 15883: 15884: 15885: 15886: 15887: 15888: 15889: 15890: 15891: 15892: 15893: 15894: 15895: 15896: 15897: 15898: 15899: 15900: 15901: 15902: 15903: 15904: 15905: 15906: 15907: 15908: 15909: 15910: 15911: 15912: 15913: 15914: 15915: 15916: 15917: 15918: 15919: 15920: 15921: 15922: 15923: 15924: 15925: 15926: 15927: 15928: 15929: 15930: 15931: 15932: 15933: 15934: 15935: 15936: 15937: 15938: 15939: 15940: 15941: 15942: 15943: 15944: 15945: 15946: 15947: 15948: 15949: 15950: 15951: 15952: 15953: 15954: 15955: 15956: 15957: 15958: 15959: 15960: 15961: 15962: 15963: 15964: 15965: 15966: 15967: 15968: 15969: 15970: 15971: 15972: 15973: 15974: 15975: 15976: 15977: 15978: 15979: 15980: 15981: 15982: 15983: 15984: 15985: 15986: 15987: 15988: 15989: 15990: 15991: 15992: 15993: 15994: 15995: 15996: 15997: 15998: 15999: 16000: 16001: 16002: 16003: 16004: 16005: 16006: 16007: 16008: 16009: 16010: 16011: 16012: 16013: 16014: 16015: 16016: 16017: 16018: 16019: 16020: 16021: 16022: 16023: 16024: 16025: 16026: 16027: 16028: 16029: 16030: 16031: 16032: 16033: 16034: 16035: 16036: 16037: 16038: 16039: 16040: 16041: 16042: 16043: 16044: 16045: 16046: 16047: 16048: 16049: 16050: 16051: 16052: 16053: 16054: 16055: 16056: 16057: 16058: 16059: 16060: 16061: 16062: 16063: 16064: 16065: 16066: 16067: 16068: 16069: 16070: 16071: 16072: 16073: 16074: 16075: 16076: 16077: 16078: 16079: 16080: 16081: 16082: 16083: 16084: 16085: 16086: 16087: 16088: 16089: 16090: 16091: 16092: 16093: 16094: 16095: 16096: 16097: 16098: 16099: 16100: 16101: 16102: 16103: 16104: 16105: 16106: 16107: 16108: 16109: 16110: 16111: 16112: 16113: 16114: 16115: 16116: 16117: 16118: 16119: 16120: 16121: 16122: 16123: 16124: 16125: 16126: 16127: 16128: 16129: 16130: 16131: 16132: 16133: 16134: 16135: 16136: 16137: 16138: 16139: 16140: 16141: 16142: 16143: 16144: 16145: 16146: 16147: 16148: 16149: 16150: 16151: 16152: 16153: 16154: 16155: 16156: 16157: 16158: 16159: 16160: 16161: 16162: 16163: 16164: 16165: 16166: 16167: 16168: 16169: 16170: 16171: 16172: 16173: 16174: 16175: 16176: 16177: 16178: 16179: 16180: 16181: 16182: 16183: 16184: 16185: 16186: 16187: 16188: 16189: 16190: 16191: 16192: 16193: 16194: 16195: 16196: 16197: 16198: 16199: 16200: 16201: 16202: 16203: 16204: 16205: 16206: 16207: 16208: 16209: 16210: 16211: 16212: 16213: 16214: 16215: 16216: 16217: 16218: 16219: 16220: 16221: 16222: 16223: 16224: 16225: 16226: 16227: 16228: 16229: 16230: 16231: 16232: 16233: 16234: 16235: 16236: 16237: 16238: 16239: 16240: 16241: 16242: 16243: 16244: 16245: 16246: 16247: 16248: 16249: 16250: 16251: 16252: 16253: 16254: 16255: 16256: 16257: 16258: 16259: 16260: 16261: 16262: 16263: 16264: 16265: 16266: 16267: 16268: 16269: 16270: 16271: 16272: 16273: 16274: 16275: 16276: 16277: 16278: 16279: 16280: 16281: 16282: 16283: 16284: 16285: 16286: 16287: 16288: 16289: 16290: 16291: 16292: 16293: 16294: 16295: 16296: 16297: 16298: 16299: 16300: 16301: 16302: 16303: 16304: 16305: 16306: 16307: 16308: 16309: 16310: 16311: 16312: 16313: 16314: 16315: 16316: 16317: 16318: 16319: 16320: 16321: 16322: 16323: 16324: 16325: 16326: 16327: 16328: 16329: 16330: 16331: 16332: 16333: 16334: 16335: 16336: 16337: 16338: 16339: 16340: 16341: 16342: 16343: 16344: 16345: 16346: 16347: 16348: 16349: 16350: 16351: 16352: 16353: 16354: 16355: 16356: 16357: 16358: 16359: 16360: 16361: 16362: 16363: 16364: 16365: 16366: 16367: 16368: 16369: 16370: 16371: 16372: 16373: 16374: 16375: 16376: 16377: 16378: 16379: 16380: 16381: 16382: 16383: 16384: 16385: 16386: 16387: 16388: 16389: 16390: 16391: 16392: 16393: 16394: 16395: 16396: 16397: 16398: 16399: 16400: 16401: 16402: 16403: 16404: 16405: 16406: 16407: 16408: 16409: 16410: 16411: 16412: 16413: 16414: 16415: 16416: 16417: 16418: 16419: 16420: 16421: 16422: 16423: 16424: 16425: 16426: 16427: 16428: 16429: 16430: 16431: 16432: 16433: 16434: 16435: 16436: 16437: 16438: 16439: 16440: 16441: 16442: 16443: 16444: 16445: 16446: 16447: 16448: 16449: 16450: 16451: 16452: 16453: 16454: 16455: 16456: 16457: 16458: 16459: 16460: 16461: 16462: 16463: 16464: 16465: 16466: 16467: 16468: 16469: 16470: 16471: 16472: 16473: 16474: 16475: 16476: 16477: 16478: 16479: 16480: 16481: 16482: 16483: 16484: 16485: 16486: 16487: 16488: 16489: 16490: 16491: 16492: 16493: 16494: 16495: 16496: 16497: 16498: 16499: 16500: 16501: 16502: 16503: 16504: 16505: 16506: 16507: 16508: 16509: 16510: 16511: 16512: 16513: 16514: 16515: 16516: 16517: 16518: 16519: 16520: 16521: 16522: 16523: 16524: 16525: 16526: 16527: 16528: 16529: 16530: 16531: 16532: 16533: 16534: 16535: 16536: 16537: 16538: 16539: 16540: 16541: 16542: 16543: 16544: 16545: 16546: 16547: 16548: 16549: 16550: 16551: 16552: 16553: 16554: 16555: 16556: 16557: 16558: 16559: 16560: 16561: 16562: 16563: 16564: 16565: 16566: 16567: 16568: 16569: 16570: 16571: 16572: 16573: 16574: 16575: 16576: 16577: 16578: 16579: 16580: 16581: 16582: 16583: 16584: 16585: 16586: 16587: 16588: 16589: 16590: 16591: 16592: 16593: 16594: 16595: 16596: 16597: 16598: 16599: 16600: 16601: 16602: 16603: 16604: 16605: 16606: 16607: 16608: 16609: 16610: 16611: 16612: 16613: 16614: 16615: 16616: 16617: 16618: 16619: 16620: 16621: 16622: 16623: 16624: 16625: 16626: 16627: 16628: 16629: 16630: 16631: 16632: 16633: 16634: 16635: 16636: 16637: 16638: 16639: 16640: 16641: 16642: 16643: 16644: 16645: 16646: 16647: 16648: 16649: 16650: 16651: 16652: 16653: 16654: 16655: 16656: 16657: 16658: 16659: 16660: 16661: 16662: 16663: 16664: 16665: 16666: 16667: 16668: 16669: 16670: 16671: 16672: 16673: 16674: 16675: 16676: 16677: 16678: 16679: 16680: 16681: 16682: 16683: 16684: 16685: 16686: 16687: 16688: 16689: 16690: 16691: 16692: 16693: 16694: 16695: 16696: 16697: 16698: 16699: 16700: 16701: 16702: 16703: 16704: 16705: 16706: 16707: 16708: 16709: 16710: 16711: 16712: 16713: 16714: 16715: 16716: 16717: 16718: 16719: 16720: 16721: 16722: 16723: 16724: 16725: 16726: 16727: 16728: 16729: 16730: 16731: 16732: 16733: 16734: 16735: 16736: 16737: 16738: 16739: 16740: 16741: 16742: 16743: 16744: 16745: 16746: 16747: 16748: 16749: 16750: 16751: 16752: 16753: 16754: 16755: 16756: 16757: 16758: 16759: 16760: 16761: 16762: 16763: 16764: 16765: 16766: 16767: 16768: 16769: 16770: 16771: 16772: 16773: 16774: 16775: 16776: 16777: 16778: 16779: 16780: 16781: 16782: 16783: 16784: 16785: 16786: 16787: 16788: 16789: 16790: 16791: 16792: 16793: 16794: 16795: 16796: 16797: 16798: 16799: 16800: 16801: 16802: 16803: 16804: 16805: 16806: 16807: 16808: 16809: 16810: 16811: 16812: 16813: 16814: 16815: 16816: 16817: 16818: 16819: 16820: 16821: 16822: 16823: 16824: 16825: 16826: 16827: 16828: 16829: 16830: 16831: 16832: 16833: 16834: 16835: 16836: 16837: 16838: 16839: 16840: 16841: 16842: 16843: 16844: 16845: 16846: 16847: 16848: 16849: 16850: 16851: 16852: 16853: 16854: 16855: 16856: 16857: 16858: 16859: 16860: 16861: 16862: 16863: 16864: 16865: 16866: 16867: 16868: 16869: 16870: 16871: 16872: 16873: 16874: 16875: 16876: 16877: 16878: 16879: 16880: 16881: 16882: 16883: 16884: 16885: 16886: 16887: 16888: 16889: 16890: 16891: 16892: 16893: 16894: 16895: 16896: 16897: 16898: 16899: 16900: 16901: 16902: 16903: 16904: 16905: 16906: 16907: 16908: 16909: 16910: 16911: 16912: 16913: 16914: 16915: 16916: 16917: 16918: 16919: 16920: 16921: 16922: 16923: 16924: 16925: 16926: 16927: 16928: 16929: 16930: 16931: 16932: 16933: 16934: 16935: 16936: 16937: 16938: 16939: 16940: 16941: 16942: 16943: 16944: 16945: 16946: 16947: 16948: 16949: 16950: 16951: 16952: 16953: 16954: 16955: 16956: 16957: 16958: 16959: 16960: 16961: 16962: 16963: 16964: 16965: 16966: 16967: 16968: 16969: 16970: 16971: 16972: 16973: 16974: 16975: 16976: 16977: 16978: 16979: 16980: 16981: 16982: 16983: 16984: 16985: 16986: 16987: 16988: 16989: 16990: 16991: 16992: 16993: 16994: 16995: 16996: 16997: 16998: 16999: 17000: 17001: 17002: 17003: 17004: 17005: 17006: 17007: 17008: 17009: 17010: 17011: 17012: 17013: 17014: 17015: 17016: 17017: 17018: 17019: 17020: 17021: 17022: 17023: 17024: 17025: 17026: 17027: 17028: 17029: 17030: 17031: 17032: 17033: 17034: 17035: 17036: 17037: 17038: 17039: 17040: 17041: 17042: 17043: 17044: 17045: 17046: 17047: 17048: 17049: 17050: 17051: 17052: 17053: 17054: 17055: 17056: 17057: 17058: 17059: 17060: 17061: 17062: 17063: 17064: 17065: 17066: 17067: 17068: 17069: 17070: 17071: 17072: 17073: 17074: 17075: 17076: 17077: 17078: 17079: 17080: 17081: 17082: 17083: 17084: 17085: 17086: 17087: 17088: 17089: 17090: 17091: 17092: 17093: 17094: 17095: 17096: 17097: 17098: 17099: 17100: 17101: 17102: 17103: 17104: 17105: 17106: 17107: 17108: 17109: 17110: 17111: 17112: 17113: 17114: 17115: 17116: 17117: 17118: 17119: 17120: 17121: 17122: 17123: 17124: 17125: 17126: 17127: 17128: 17129: 17130: 17131: 17132: 17133: 17134: 17135: 17136: 17137: 17138: 17139: 17140: 17141: 17142: 17143: 17144: 17145: 17146: 17147: 17148: 17149: 17150: 17151: 17152: 17153: 17154: 17155: 17156: 17157: 17158: 17159: 17160: 17161: 17162: 17163: 17164: 17165: 17166: 17167: 17168: 17169: 17170: 17171: 17172: 17173: 17174: 17175: 17176: 17177: 17178: 17179: 17180: 17181: 17182: 17183: 17184: 17185: 17186: 17187: 17188: 17189: 17190: 17191: 17192: 17193: 17194: 17195: 17196: 17197: 17198: 17199: 17200: 17201: 17202: 17203: 17204: 17205: 17206: 17207: 17208: 17209: 17210: 17211: 17212: 17213: 17214: 17215: 17216: 17217: 17218: 17219: 17220: 17221: 17222: 17223: 17224: 17225: 17226: 17227: 17228: 17229: 17230: 17231: 17232: 17233: 17234: 17235: 17236: 17237: 17238: 17239: 17240: 17241: 17242: 17243: 17244: 17245: 17246: 17247: 17248: 17249: 17250: 17251: 17252: 17253: 17254: 17255: 17256: 17257: 17258: 17259: 17260: 17261: 17262: 17263: 17264: 17265: 17266: 17267: 17268: 17269: 17270: 17271: 17272: 17273: 17274: 17275: 17276: 17277: 17278: 17279: 17280: 17281: 17282: 17283: 17284: 17285: 17286: 17287: 17288: 17289: 17290: 17291: 17292: 17293: 17294: 17295: 17296: 17297: 17298: 17299: 17300: 17301: 17302: 17303: 17304: 17305: 17306: 17307: 17308: 17309: 17310: 17311: 17312: 17313: 17314: 17315: 17316: 17317: 17318: 17319: 17320: 17321: 17322: 17323: 17324: 17325: 17326: 17327: 17328: 17329: 17330: 17331: 17332: 17333: 17334: 17335: 17336: 17337: 17338: 17339: 17340: 17341: 17342: 17343: 17344: 17345: 17346: 17347: 17348: 17349: 17350: 17351: 17352: 17353: 17354: 17355: 17356: 17357: 17358: 17359: 17360: 17361: 17362: 17363: 17364: 17365: 17366: 17367: 17368: 17369: 17370: 17371: 17372: 17373: 17374: 17375: 17376: 17377: 17378: 17379: 17380: 17381: 17382: 17383: 17384: 17385: 17386: 17387: 17388: 17389: 17390: 17391: 17392: 17393: 17394: 17395: 17396: 17397: 17398: 17399: 17400: 17401: 17402: 17403: 17404: 17405: 17406: 17407: 17408: 17409: 17410: 17411: 17412: 17413: 17414: 17415: 17416: 17417: 17418: 17419: 17420: 17421: 17422: 17423: 17424: 17425: 17426: 17427: 17428: 17429: 17430: 17431: 17432: 17433: 17434: 17435: 17436: 17437: 17438: 17439: 17440: 17441: 17442: 17443: 17444: 17445: 17446: 17447: 17448: 17449: 17450: 17451: 17452: 17453: 17454: 17455: 17456: 17457: 17458: 17459: 17460: 17461: 17462: 17463: 17464: 17465: 17466: 17467: 17468: 17469: 17470: 17471: 17472: 17473: 17474: 17475: 17476: 17477: 17478: 17479: 17480: 17481: 17482: 17483: 17484: 17485: 17486: 17487: 17488: 17489: 17490: 17491: 17492: 17493: 17494: 17495: 17496: 17497: 17498: 17499: 17500: 17501: 17502: 17503: 17504: 17505: 17506: 17507: 17508: 17509: 17510: 17511: 17512: 17513: 17514: 17515: 17516: 17517: 17518: 17519: 17520: 17521: 17522: 17523: 17524: 17525: 17526: 17527: 17528: 17529: 17530: 17531: 17532: 17533: 17534: 17535: 17536: 17537: 17538: 17539: 17540: 17541: 17542: 17543: 17544: 17545: 17546: 17547: 17548: 17549: 17550: 17551: 17552: 17553: 17554: 17555: 17556: 17557: 17558: 17559: 17560: 17561: 17562: 17563: 17564: 17565: 17566: 17567: 17568: 17569: 17570: 17571: 17572: 17573: 17574: 17575: 17576: 17577: 17578: 17579: 17580: 17581: 17582: 17583: 17584: 17585: 17586: 17587: 17588: 17589: 17590: 17591: 17592: 17593: 17594: 17595: 17596: 17597: 17598: 17599: 17600: 17601: 17602: 17603: 17604: 17605: 17606: 17607: 17608: 17609: 17610: 17611: 17612: 17613: 17614: 17615: 17616: 17617: 17618: 17619: 17620: 17621: 17622: 17623: 17624: 17625: 17626: 17627: 17628: 17629: 17630: 17631: 17632: 17633: 17634: 17635: 17636: 17637: 17638: 17639: 17640: 17641: 17642: 17643: 17644: 17645: 17646: 17647: 17648: 17649: 17650: 17651: 17652: 17653: 17654: 17655: 17656: 17657: 17658: 17659: 17660: 17661: 17662: 17663: 17664: 17665: 17666: 17667: 17668: 17669: 17670: 17671: 17672: 17673: 17674: 17675: 17676: 17677: 17678: 17679: 17680: 17681: 17682: 17683: 17684: 17685: 17686: 17687: 17688: 17689: 17690: 17691: 17692: 17693: 17694: 17695: 17696: 17697: 17698: 17699: 17700: 17701: 17702: 17703: 17704: 17705: 17706: 17707: 17708: 17709: 17710: 17711: 17712: 17713: 17714: 17715: 17716: 17717: 17718: 17719: 17720: 17721: 17722: 17723: 17724: 17725: 17726: 17727: 17728: 17729: 17730: 17731: 17732: 17733: 17734: 17735: 17736: 17737: 17738: 17739: 17740: 17741: 17742: 17743: 17744: 17745: 17746: 17747: 17748: 17749: 17750: 17751: 17752: 17753: 17754: 17755: 17756: 17757: 17758: 17759: 17760: 17761: 17762: 17763: 17764: 17765: 17766: 17767: 17768: 17769: 17770: 17771: 17772: 17773: 17774: 17775: 17776: 17777: 17778: 17779: 17780: 17781: 17782: 17783: 17784: 17785: 17786: 17787: 17788: 17789: 17790: 17791: 17792: 17793: 17794: 17795: 17796: 17797: 17798: 17799: 17800: 17801: 17802: 17803: 17804: 17805: 17806: 17807: 17808: 17809: 17810: 17811: 17812: 17813: 17814: 17815: 17816: 17817: 17818: 17819: 17820: 17821: 17822: 17823: 17824: 17825: 17826: 17827: 17828: 17829: 17830: 17831: 17832: 17833: 17834: 17835: 17836: 17837: 17838: 17839: 17840: 17841: 17842: 17843: 17844: 17845: 17846: 17847: 17848: 17849: 17850: 17851: 17852: 17853: 17854: 17855: 17856: 17857: 17858: 17859: 17860: 17861: 17862: 17863: 17864: 17865: 17866: 17867: 17868: 17869: 17870: 17871: 17872: 17873: 17874: 17875: 17876: 17877: 17878: 17879: 17880: 17881: 17882: 17883: 17884: 17885: 17886: 17887: 17888: 17889: 17890: 17891: 17892: 17893: 17894: 17895: 17896: 17897: 17898: 17899: 17900: 17901: 17902: 17903: 17904: 17905: 17906: 17907: 17908: 17909: 17910: 17911: 17912: 17913: 17914: 17915: 17916: 17917: 17918: 17919: 17920: 17921: 17922: 17923: 17924: 17925: 17926: 17927: 17928: 17929: 17930: 17931: 17932: 17933: 17934: 17935: 17936: 17937: 17938: 17939: 17940: 17941: 17942: 17943: 17944: 17945: 17946: 17947: 17948: 17949: 17950: 17951: 17952: 17953: 17954: 17955: 17956: 17957: 17958: 17959: 17960: 17961: 17962: 17963: 17964: 17965: 17966: 17967: 17968: 17969: 17970: 17971: 17972: 17973: 17974: 17975: 17976: 17977: 17978: 17979: 17980: 17981: 17982: 17983: 17984: 17985: 17986: 17987: 17988: 17989: 17990: 17991: 17992: 17993: 17994: 17995: 17996: 17997: 17998: 17999: 18000: 18001: 18002: 18003: 18004: 18005: 18006: 18007: 18008: 18009: 18010: 18011: 18012: 18013: 18014: 18015: 18016: 18017: 18018: 18019: 18020: 18021: 18022: 18023: 18024: 18025: 18026: 18027: 18028: 18029: 18030: 18031: 18032: 18033: 18034: 18035: 18036: 18037: 18038: 18039: 18040: 18041: 18042: 18043: 18044: 18045: 18046: 18047: 18048: 18049: 18050: 18051: 18052: 18053: 18054: 18055: 18056: 18057: 18058: 18059: 18060: 18061: 18062: 18063: 18064: 18065: 18066: 18067: 18068: 18069: 18070: 18071: 18072: 18073: 18074: 18075: 18076: 18077: 18078: 18079: 18080: 18081: 18082: 18083: 18084: 18085: 18086: 18087: 18088: 18089: 18090: 18091: 18092: 18093: 18094: 18095: 18096: 18097: 18098: 18099: 18100: 18101: 18102: 18103: 18104: 18105: 18106: 18107: 18108: 18109: 18110: 18111: 18112: 18113: 18114: 18115: 18116: 18117: 18118: 18119: 18120: 18121: 18122: 18123: 18124: 18125: 18126: 18127: 18128: 18129: 18130: 18131: 18132: 18133: 18134: 18135: 18136: 18137: 18138: 18139: 18140: 18141: 18142: 18143: 18144: 18145: 18146: 18147: 18148: 18149: 18150: 18151: 18152: 18153: 18154: 18155: 18156: 18157: 18158: 18159: 18160: 18161: 18162: 18163: 18164: 18165: 18166: 18167: 18168: 18169: 18170: 18171: 18172: 18173: 18174: 18175: 18176: 18177: 18178: 18179: 18180: 18181: 18182: 18183: 18184: 18185: 18186: 18187: 18188: 18189: 18190: 18191: 18192: 18193: 18194: 18195: 18196: 18197: 18198: 18199: 18200: 18201: 18202: 18203: 18204: 18205: 18206: 18207: 18208: 18209: 18210: 18211: 18212: 18213: 18214: 18215: 18216: 18217: 18218: 18219: 18220: 18221: 18222: 18223: 18224: 18225: 18226: 18227: 18228: 18229: 18230: 18231: 18232: 18233: 18234: 18235: 18236: 18237: 18238: 18239: 18240: 18241: 18242: 18243: 18244: 18245: 18246: 18247: 18248: 18249: 18250: 18251: 18252: 18253: 18254: 18255: 18256: 18257: 18258: 18259: 18260: 18261: 18262: 18263: 18264: 18265: 18266: 18267: 18268: 18269: 18270: 18271: 18272: 18273: 18274: 18275: 18276: 18277: 18278: 18279: 18280: 18281: 18282: 18283: 18284: 18285: 18286: 18287: 18288: 18289: 18290: 18291: 18292: 18293: 18294: 18295: 18296: 18297: 18298: 18299: 18300: 18301: 18302: 18303: 18304: 18305: 18306: 18307: 18308: 18309: 18310: 18311: 18312: 18313: 18314: 18315: 18316: 18317: 18318: 18319: 18320: 18321: 18322: 18323: 18324: 18325: 18326: 18327: 18328: 18329: 18330: 18331: 18332: 18333: 18334: 18335: 18336: 18337: 18338: 18339: 18340: 18341: 18342: 18343: 18344: 18345: 18346: 18347: 18348: 18349: 18350: 18351: 18352: 18353: 18354: 18355: 18356: 18357: 18358: 18359: 18360: 18361: 18362: 18363: 18364: 18365: 18366: 18367: 18368: 18369: 18370: 18371: 18372: 18373: 18374: 18375: 18376: 18377: 18378: 18379: 18380: 18381: 18382: 18383: 18384: 18385: 18386: 18387: 18388: 18389: 18390: 18391: 18392: 18393: 18394: 18395: 18396: 18397: 18398: 18399: 18400: 18401: 18402: 18403: 18404: 18405: 18406: 18407: 18408: 18409: 18410: 18411: 18412: 18413: 18414: 18415: 18416: 18417: 18418: 18419: 18420: 18421: 18422: 18423: 18424: 18425: 18426: 18427: 18428: 18429: 18430: 18431: 18432: 18433: 18434: 18435: 18436: 18437: 18438: 18439: 18440: 18441: 18442: 18443: 18444: 18445: 18446: 18447: 18448: 18449: 18450: 18451: 18452: 18453: 18454: 18455: 18456: 18457: 18458: 18459: 18460: 18461: 18462: 18463: 18464: 18465: 18466: 18467: 18468: 18469: 18470: 18471: 18472: 18473: 18474: 18475: 18476: 18477: 18478: 18479: 18480: 18481: 18482: 18483: 18484: 18485: 18486: 18487: 18488: 18489: 18490: 18491: 18492: 18493: 18494: 18495: 18496: 18497: 18498: 18499: 18500: 18501: 18502: 18503: 18504: 18505: 18506: 18507: 18508: 18509: 18510: 18511: 18512: 18513: 18514: 18515: 18516: 18517: 18518: 18519: 18520: 18521: 18522: 18523: 18524: 18525: 18526: 18527: 18528: 18529: 18530: 18531: 18532: 18533: 18534: 18535: 18536: 18537: 18538: 18539: 18540: 18541: 18542: 18543: 18544: 18545: 18546: 18547: 18548: 18549: 18550: 18551: 18552: 18553: 18554: 18555: 18556: 18557: 18558: 18559: 18560: 18561: 18562: 18563: 18564: 18565: 18566: 18567: 18568: 18569: 18570: 18571: 18572: 18573: 18574: 18575: 18576: 18577: 18578: 18579: 18580: 18581: 18582: 18583: 18584: 18585: 18586: 18587: 18588: 18589: 18590: 18591: 18592: 18593: 18594: 18595: 18596: 18597: 18598: 18599: 18600: 18601: 18602: 18603: 18604: 18605: 18606: 18607: 18608: 18609: 18610: 18611: 18612: 18613: 18614: 18615: 18616: 18617: 18618: 18619: 18620: 18621: 18622: 18623: 18624: 18625: 18626: 18627: 18628: 18629: 18630: 18631: 18632: 18633: 18634: 18635: 18636: 18637: 18638: 18639: 18640: 18641: 18642: 18643: 18644: 18645: 18646: 18647: 18648: 18649: 18650: 18651: 18652: 18653: 18654: 18655: 18656: 18657: 18658: 18659: 18660: 18661: 18662: 18663: 18664: 18665: 18666: 18667: 18668: 18669: 18670: 18671: 18672: 18673: 18674: 18675: 18676: 18677: 18678: 18679: 18680: 18681: 18682: 18683: 18684: 18685: 18686: 18687: 18688: 18689: 18690: 18691: 18692: 18693: 18694: 18695: 18696: 18697: 18698: 18699: 18700: 18701: 18702: 18703: 18704: 18705: 18706: 18707: 18708: 18709: 18710: 18711: 18712: 18713: 18714: 18715: 18716: 18717: 18718: 18719: 18720: 18721: 18722: 18723: 18724: 18725: 18726: 18727: 18728: 18729: 18730: 18731: 18732: 18733: 18734: 18735: 18736: 18737: 18738: 18739: 18740: 18741: 18742: 18743: 18744: 18745: 18746: 18747: 18748: 18749: 18750: 18751: 18752: 18753: 18754: 18755: 18756: 18757: 18758: 18759: 18760: 18761: 18762: 18763: 18764: 18765: 18766: 18767: 18768: 18769: 18770: 18771: 18772: 18773: 18774: 18775: 18776: 18777: 18778: 18779: 18780: 18781: 18782: 18783: 18784: 18785: 18786: 18787: 18788: 18789: 18790: 18791: 18792: 18793: 18794: 18795: 18796: 18797: 18798: 18799: 18800: 18801: 18802: 18803: 18804: 18805: 18806: 18807: 18808: 18809: 18810: 18811: 18812: 18813: 18814: 18815: 18816: 18817: 18818: 18819: 18820: 18821: 18822: 18823: 18824: 18825: 18826: 18827: 18828: 18829: 18830: 18831: 18832: 18833: 18834: 18835: 18836: 18837: 18838: 18839: 18840: 18841: 18842: 18843: 18844: 18845: 18846: 18847: 18848: 18849: 18850: 18851: 18852: 18853: 18854: 18855: 18856: 18857: 18858: 18859: 18860: 18861: 18862: 18863: 18864: 18865: 18866: 18867: 18868: 18869: 18870: 18871: 18872: 18873: 18874: 18875: 18876: 18877: 18878: 18879: 18880: 18881: 18882: 18883: 18884: 18885: 18886: 18887: 18888: 18889: 18890: 18891: 18892: 18893: 18894: 18895: 18896: 18897: 18898: 18899: 18900: 18901: 18902: 18903: 18904: 18905: 18906: 18907: 18908: 18909: 18910: 18911: 18912: 18913: 18914: 18915: 18916: 18917: 18918: 18919: 18920: 18921: 18922: 18923: 18924: 18925: 18926: 18927: 18928: 18929: 18930: 18931: 18932: 18933: 18934: 18935: 18936: 18937: 18938: 18939: 18940: 18941: 18942: 18943: 18944: 18945: 18946: 18947: 18948: 18949: 18950: 18951: 18952: 18953: 18954: 18955: 18956: 18957: 18958: 18959: 18960: 18961: 18962: 18963: 18964: 18965: 18966: 18967: 18968: 18969: 18970: 18971: 18972: 18973: 18974: 18975: 18976: 18977: 18978: 18979: 18980: 18981: 18982: 18983: 18984: 18985: 18986: 18987: 18988: 18989: 18990: 18991: 18992: 18993: 18994: 18995: 18996: 18997: 18998: 18999: 19000: 19001: 19002: 19003: 19004: 19005: 19006: 19007: 19008: 19009: 19010: 19011: 19012: 19013: 19014: 19015: 19016: 19017: 19018: 19019: 19020: 19021: 19022: 19023: 19024: 19025: 19026: 19027: 19028: 19029: 19030: 19031: 19032: 19033: 19034: 19035: 19036: 19037: 19038: 19039: 19040: 19041: 19042: 19043: 19044: 19045: 19046: 19047: 19048: 19049: 19050: 19051: 19052: 19053: 19054: 19055: 19056: 19057: 19058: 19059: 19060: 19061: 19062: 19063: 19064: 19065: 19066: 19067: 19068: 19069: 19070: 19071: 19072: 19073: 19074: 19075: 19076: 19077: 19078: 19079: 19080: 19081: 19082: 19083: 19084: 19085: 19086: 19087: 19088: 19089: 19090: 19091: 19092: 19093: 19094: 19095: 19096: 19097: 19098: 19099: 19100: 19101: 19102: 19103: 19104: 19105: 19106: 19107: 19108: 19109: 19110: 19111: 19112: 19113: 19114: 19115: 19116: 19117: 19118: 19119: 19120: 19121: 19122: 19123: 19124: 19125: 19126: 19127: 19128: 19129: 19130: 19131: 19132: 19133: 19134: 19135: 19136: 19137: 19138: 19139: 19140: 19141: 19142: 19143: 19144: 19145: 19146: 19147: 19148: 19149: 19150: 19151: 19152: 19153: 19154: 19155: 19156: 19157: 19158: 19159: 19160: 19161: 19162: 19163: 19164: 19165: 19166: 19167: 19168: 19169: 19170: 19171: 19172: 19173: 19174: 19175: 19176: 19177: 19178: 19179: 19180: 19181: 19182: 19183: 19184: 19185: 19186: 19187: 19188: 19189: 19190: 19191: 19192: 19193: 19194: 19195: 19196: 19197: 19198: 19199: 19200: 19201: 19202: 19203: 19204: 19205: 19206: 19207: 19208: 19209: 19210: 19211: 19212: 19213: 19214: 19215: 19216: 19217: 19218: 19219: 19220: 19221: 19222: 19223: 19224: 19225: 19226: 19227: 19228: 19229: 19230: 19231: 19232: 19233: 19234: 19235: 19236: 19237: 19238: 19239: 19240: 19241: 19242: 19243: 19244: 19245: 19246: 19247: 19248: 19249: 19250: 19251: 19252: 19253: 19254: 19255: 19256: 19257: 19258: 19259: 19260: 19261: 19262: 19263: 19264: 19265: 19266: 19267: 19268: 19269: 19270: 19271: 19272: 19273: 19274: 19275: 19276: 19277: 19278: 19279: 19280: 19281: 19282: 19283: 19284: 19285: 19286: 19287: 19288: 19289: 19290: 19291: 19292: 19293: 19294: 19295: 19296: 19297: 19298: 19299: 19300: 19301: 19302: 19303: 19304: 19305: 19306: 19307: 19308: 19309: 19310: 19311: 19312: 19313: 19314: 19315: 19316: 19317: 19318: 19319: 19320: 19321: 19322: 19323: 19324: 19325: 19326: 19327: 19328: 19329: 19330: 19331: 19332: 19333: 19334: 19335: 19336: 19337: 19338: 19339: 19340: 19341: 19342: 19343: 19344: 19345: 19346: 19347: 19348: 19349: 19350: 19351: 19352: 19353: 19354: 19355: 19356: 19357: 19358: 19359: 19360: 19361: 19362: 19363: 19364: 19365: 19366: 19367: 19368: 19369: 19370: 19371: 19372: 19373: 19374: 19375: 19376: 19377: 19378: 19379: 19380: 19381: 19382: 19383: 19384: 19385: 19386: 19387: 19388: 19389: 19390: 19391: 19392: 19393: 19394: 19395: 19396: 19397: 19398: 19399: 19400: 19401: 19402: 19403: 19404: 19405: 19406: 19407: 19408: 19409: 19410: 19411: 19412: 19413: 19414: 19415: 19416: 19417: 19418: 19419: 19420: 19421: 19422: 19423: 19424: 19425: 19426: 19427: 19428: 19429: 19430: 19431: 19432: 19433: 19434: 19435: 19436: 19437: 19438: 19439: 19440: 19441: 19442: 19443: 19444: 19445: 19446: 19447: 19448: 19449: 19450: 19451: 19452: 19453: 19454: 19455: 19456: 19457: 19458: 19459: 19460: 19461: 19462: 19463: 19464: 19465: 19466: 19467: 19468: 19469: 19470: 19471: 19472: 19473: 19474: 19475: 19476: 19477: 19478: 19479: 19480: 19481: 19482: 19483: 19484: 19485: 19486: 19487: 19488: 19489: 19490: 19491: 19492: 19493: 19494: 19495: 19496: 19497: 19498: 19499: 19500: 19501: 19502: 19503: 19504: 19505: 19506: 19507: 19508: 19509: 19510: 19511: 19512: 19513: 19514: 19515: 19516: 19517: 19518: 19519: 19520: 19521: 19522: 19523: 19524: 19525: 19526: 19527: 19528: 19529: 19530: 19531: 19532: 19533: 19534: 19535: 19536: 19537: 19538: 19539: 19540: 19541: 19542: 19543: 19544: 19545: 19546: 19547: 19548: 19549: 19550: 19551: 19552: 19553: 19554: 19555: 19556: 19557: 19558: 19559: 19560: 19561: 19562: 19563: 19564: 19565: 19566: 19567: 19568: 19569: 19570: 19571: 19572: 19573: 19574: 19575: 19576: 19577: 19578: 19579: 19580: 19581: 19582: 19583: 19584: 19585: 19586: 19587: 19588: 19589: 19590: 19591: 19592: 19593: 19594: 19595: 19596: 19597: 19598: 19599: 19600: 19601: 19602: 19603: 19604: 19605: 19606: 19607: 19608: 19609: 19610: 19611: 19612: 19613: 19614: 19615: 19616: 19617: 19618: 19619: 19620: 19621: 19622: 19623: 19624: 19625: 19626: 19627: 19628: 19629: 19630: 19631: 19632: 19633: 19634: 19635: 19636: 19637: 19638: 19639: 19640: 19641: 19642: 19643: 19644: 19645: 19646: 19647: 19648: 19649: 19650: 19651: 19652: 19653: 19654: 19655: 19656: 19657: 19658: 19659: 19660: 19661: 19662: 19663: 19664: 19665: 19666: 19667: 19668: 19669: 19670: 19671: 19672: 19673: 19674: 19675: 19676: 19677: 19678: 19679: 19680: 19681: 19682: 19683: 19684: 19685: 19686: 19687: 19688: 19689: 19690: 19691: 19692: 19693: 19694: 19695: 19696: 19697: 19698: 19699: 19700: 19701: 19702: 19703: 19704: 19705: 19706: 19707: 19708: 19709: 19710: 19711: 19712: 19713: 19714: 19715: 19716: 19717: 19718: 19719: 19720: 19721: 19722: 19723: 19724: 19725: 19726: 19727: 19728: 19729: 19730: 19731: 19732: 19733: 19734: 19735: 19736: 19737: 19738: 19739: 19740: 19741: 19742: 19743: 19744: 19745: 19746: 19747: 19748: 19749: 19750: 19751: 19752: 19753: 19754: 19755: 19756: 19757: 19758: 19759: 19760: 19761: 19762: 19763: 19764: 19765: 19766: 19767: 19768: 19769: 19770: 19771: 19772: 19773: 19774: 19775: 19776: 19777: 19778: 19779: 19780: 19781: 19782: 19783: 19784: 19785: 19786: 19787: 19788: 19789: 19790: 19791: 19792: 19793: 19794: 19795: 19796: 19797: 19798: 19799: 19800: 19801: 19802: 19803: 19804: 19805: 19806: 19807: 19808: 19809: 19810: 19811: 19812: 19813: 19814: 19815: 19816: 19817: 19818: 19819: 19820: 19821: 19822: 19823: 19824: 19825: 19826: 19827: 19828: 19829: 19830: 19831: 19832: 19833: 19834: 19835: 19836: 19837: 19838: 19839: 19840: 19841: 19842: 19843: 19844: 19845: 19846: 19847: 19848: 19849: 19850: 19851: 19852: 19853: 19854: 19855: 19856: 19857: 19858: 19859: 19860: 19861: 19862: 19863: 19864: 19865: 19866: 19867: 19868: 19869: 19870: 19871: 19872: 19873: 19874: 19875: 19876: 19877: 19878: 19879: 19880: 19881: 19882: 19883: 19884: 19885: 19886: 19887: 19888: 19889: 19890: 19891: 19892: 19893: 19894: 19895: 19896: 19897: 19898: 19899: 19900: 19901: 19902: 19903: 19904: 19905: 19906: 19907: 19908: 19909: 19910: 19911: 19912: 19913: 19914: 19915: 19916: 19917: 19918: 19919: 19920: 19921: 19922: 19923: 19924: 19925: 19926: 19927: 19928: 19929: 19930: 19931: 19932: 19933: 19934: 19935: 19936: 19937: 19938: 19939: 19940: 19941: 19942: 19943: 19944: 19945: 19946: 19947: 19948: 19949: 19950: 19951: 19952: 19953: 19954: 19955: 19956: 19957: 19958: 19959: 19960: 19961: 19962: 19963: 19964: 19965: 19966: 19967: 19968: 19969: 19970: 19971: 19972: 19973: 19974: 19975: 19976: 19977: 19978: 19979: 19980: 19981: 19982: 19983: 19984: 19985: 19986: 19987: 19988: 19989: 19990: 19991: 19992: 19993: 19994: 19995: 19996: 19997: 19998: 19999: 20000: 20001: 20002: 20003: 20004: 20005: 20006: 20007: 20008: 20009: 20010: 20011: 20012: 20013: 20014: 20015: 20016: 20017: 20018: 20019: 20020: 20021: 20022: 20023: 20024: 20025: 20026: 20027: 20028: 20029: 20030: 20031: 20032: 20033: 20034: 20035: 20036: 20037: 20038: 20039: 20040: 20041: 20042: 20043: 20044: 20045: 20046: 20047: 20048: 20049: 20050: 20051: 20052: 20053: 20054: 20055: 20056: 20057: 20058: 20059: 20060: 20061: 20062: 20063: 20064: 20065: 20066: 20067: 20068: 20069: 20070: 20071: 20072: 20073: 20074: 20075: 20076: 20077: 20078: 20079: 20080: 20081: 20082: 20083: 20084: 20085: 20086: 20087: 20088: 20089: 20090: 20091: 20092: 20093: 20094: 20095: 20096: 20097: 20098: 20099: 20100: 20101: 20102: 20103: 20104: 20105: 20106: 20107: 20108: 20109: 20110: 20111: 20112: 20113: 20114: 20115: 20116: 20117: 20118: 20119: 20120: 20121: 20122: 20123: 20124: 20125: 20126: 20127: 20128: 20129: 20130: 20131: 20132: 20133: 20134: 20135: 20136: 20137: 20138: 20139: 20140: 20141: 20142: 20143: 20144: 20145: 20146: 20147: 20148: 20149: 20150: 20151: 20152: 20153: 20154: 20155: 20156: 20157: 20158: 20159: 20160: 20161: 20162: 20163: 20164: 20165: 20166: 20167: 20168: 20169: 20170: 20171: 20172: 20173: 20174: 20175: 20176: 20177: 20178: 20179: 20180: 20181: 20182: 20183: 20184: 20185: 20186: 20187: 20188: 20189: 20190: 20191: 20192: 20193: 20194: 20195: 20196: 20197: 20198: 20199: 20200: 20201: 20202: 20203: 20204: 20205: 20206: 20207: 20208: 20209: 20210: 20211: 20212: 20213: 20214: 20215: 20216: 20217: 20218: 20219: 20220: 20221: 20222: 20223: 20224: 20225: 20226: 20227: 20228: 20229: 20230: 20231: 20232: 20233: 20234: 20235: 20236: 20237: 20238: 20239: 20240: 20241: 20242: 20243: 20244: 20245: 20246: 20247: 20248: 20249: 20250: 20251: 20252: 20253: 20254: 20255: 20256: 20257: 20258: 20259: 20260: 20261: 20262: 20263: 20264: 20265: 20266: 20267: 20268: 20269: 20270: 20271: 20272: 20273: 20274: 20275: 20276: 20277: 20278: 20279: 20280: 20281: 20282: 20283: 20284: 20285: 20286: 20287: 20288: 20289: 20290: 20291: 20292: 20293: 20294: 20295: 20296: 20297: 20298: 20299: 20300: 20301: 20302: 20303: 20304: 20305: 20306: 20307: 20308: 20309: 20310: 20311: 20312: 20313: 20314: 20315: 20316: 20317: 20318: 20319: 20320: 20321: 20322: 20323: 20324: 20325: 20326: 20327: 20328: 20329: 20330: 20331: 20332: 20333: 20334: 20335: 20336: 20337: 20338: 20339: 20340: 20341: 20342: 20343: 20344: 20345: 20346: 20347: 20348: 20349: 20350: 20351: 20352: 20353: 20354: 20355: 20356: 20357: 20358: 20359: 20360: 20361: 20362: 20363: 20364: 20365: 20366: 20367: 20368: 20369: 20370: 20371: 20372: 20373: 20374: 20375: 20376: 20377: 20378: 20379: 20380: 20381: 20382: 20383: 20384: 20385: 20386: 20387: 20388: 20389: 20390: 20391: 20392: 20393: 20394: 20395: 20396: 20397: 20398: 20399: 20400: 20401: 20402: 20403: 20404: 20405: 20406: 20407: 20408: 20409: 20410: 20411: 20412: 20413: 20414: 20415: 20416: 20417: 20418: 20419: 20420: 20421: 20422: 20423: 20424: 20425: 20426: 20427: 20428: 20429: 20430: 20431: 20432: 20433: 20434: 20435: 20436: 20437: 20438: 20439: 20440: 20441: 20442: 20443: 20444: 20445: 20446: 20447: 20448: 20449: 20450: 20451: 20452: 20453: 20454: 20455: 20456: 20457: 20458: 20459: 20460: 20461: 20462: 20463: 20464: 20465: 20466: 20467: 20468: 20469: 20470: 20471: 20472: 20473: 20474: 20475: 20476: 20477: 20478: 20479: 20480: 20481: 20482: 20483: 20484: 20485: 20486: 20487: 20488: 20489: 20490: 20491: 20492: 20493: 20494: 20495: 20496: 20497: 20498: 20499: 20500: 20501: 20502: 20503: 20504: 20505: 20506: 20507: 20508: 20509: 20510: 20511: 20512: 20513: 20514: 20515: 20516: 20517: 20518: 20519: 20520: 20521: 20522: 20523: 20524: 20525: 20526: 20527: 20528: 20529: 20530: 20531: 20532: 20533: 20534: 20535: 20536: 20537: 20538: 20539: 20540: 20541: 20542: 20543: 20544: 20545: 20546: 20547: 20548: 20549: 20550: 20551: 20552: 20553: 20554: 20555: 20556: 20557: 20558: 20559: 20560: 20561: 20562: 20563: 20564: 20565: 20566: 20567: 20568: 20569: 20570: 20571: 20572: 20573: 20574: 20575: 20576: 20577: 20578: 20579: 20580: 20581: 20582: 20583: 20584: 20585: 20586: 20587: 20588: 20589: 20590: 20591: 20592: 20593: 20594: 20595: 20596: 20597: 20598: 20599: 20600: 20601: 20602: 20603: 20604: 20605: 20606: 20607: 20608: 20609: 20610: 20611: 20612: 20613: 20614: 20615: 20616: 20617: 20618: 20619: 20620: 20621: 20622: 20623: 20624: 20625: 20626: 20627: 20628: 20629: 20630: 20631: 20632: 20633: 20634: 20635: 20636: 20637: 20638: 20639: 20640: 20641: 20642: 20643: 20644: 20645: 20646: 20647: 20648: 20649: 20650: 20651: 20652: 20653: 20654: 20655: 20656: 20657: 20658: 20659: 20660: 20661: 20662: 20663: 20664: 20665: 20666: 20667: 20668: 20669: 20670: 20671: 20672: 20673: 20674: 20675: 20676: 20677: 20678: 20679: 20680: 20681: 20682: 20683: 20684: 20685: 20686: 20687: 20688: 20689: 20690: 20691: 20692: 20693: 20694: 20695: 20696: 20697: 20698: 20699: 20700: 20701: 20702: 20703: 20704: 20705: 20706: 20707: 20708: 20709: 20710: 20711: 20712: 20713: 20714: 20715: 20716: 20717: 20718: 20719: 20720: 20721: 20722: 20723: 20724: 20725: 20726: 20727: 20728: 20729: 20730: 20731: 20732: 20733: 20734: 20735: 20736: 20737: 20738: 20739: 20740: 20741: 20742: 20743: 20744: 20745: 20746: 20747: 20748: 20749: 20750: 20751: 20752: 20753: 20754: 20755: 20756: 20757: 20758: 20759: 20760: 20761: 20762: 20763: 20764: 20765: 20766: 20767: 20768: 20769: 20770: 20771: 20772: 20773: 20774: 20775: 20776: 20777: 20778: 20779: 20780: 20781: 20782: 20783: 20784: 20785: 20786: 20787: 20788: 20789: 20790: 20791: 20792: 20793: 20794: 20795: 20796: 20797: 20798: 20799: 20800: 20801: 20802: 20803: 20804: 20805: 20806: 20807: 20808: 20809: 20810: 20811: 20812: 20813: 20814: 20815: 20816: 20817: 20818: 20819: 20820: 20821: 20822: 20823: 20824: 20825: 20826: 20827: 20828: 20829: 20830: 20831: 20832: 20833: 20834: 20835: 20836: 20837: 20838: 20839: 20840: 20841: 20842: 20843: 20844: 20845: 20846: 20847: 20848: 20849: 20850: 20851: 20852: 20853: 20854: 20855: 20856: 20857: 20858: 20859: 20860: 20861: 20862: 20863: 20864: 20865: 20866: 20867: 20868: 20869: 20870: 20871: 20872: 20873: 20874: 20875: 20876: 20877: 20878: 20879: 20880: 20881: 20882: 20883: 20884: 20885: 20886: 20887: 20888: 20889: 20890: 20891: 20892: 20893: 20894: 20895: 20896: 20897: 20898: 20899: 20900: 20901: 20902: 20903: 20904: 20905: 20906: 20907: 20908: 20909: 20910: 20911: 20912: 20913: 20914: 20915: 20916: 20917: 20918: 20919: 20920: 20921: 20922: 20923: 20924: 20925: 20926: 20927: 20928: 20929: 20930: 20931: 20932: 20933: 20934: 20935: 20936: 20937: 20938: 20939: 20940: 20941: 20942: 20943: 20944: 20945: 20946: 20947: 20948: 20949: 20950: 20951: 20952: 20953: 20954: 20955: 20956: 20957: 20958: 20959: 20960: 20961: 20962: 20963: 20964: 20965: 20966: 20967: 20968: 20969: 20970: 20971: 20972: 20973: 20974: 20975: 20976: 20977: 20978: 20979: 20980: 20981: 20982: 20983: 20984: 20985: 20986: 20987: 20988: 20989: 20990: 20991: 20992: 20993: 20994: 20995: 20996: 20997: 20998: 20999: 21000: 21001: 21002: 21003: 21004: 21005: 21006: 21007: 21008: 21009: 21010: 21011: 21012: 21013: 21014: 21015: 21016: 21017: 21018: 21019: 21020: 21021: 21022: 21023: 21024: 21025: 21026: 21027: 21028: 21029: 21030: 21031: 21032: 21033: 21034: 21035: 21036: 21037: 21038: 21039: 21040: 21041: 21042: 21043: 21044: 21045: 21046: 21047: 21048: 21049: 21050: 21051: 21052: 21053: 21054: 21055: 21056: 21057: 21058: 21059: 21060: 21061: 21062: 21063: 21064: 21065: 21066: 21067: 21068: 21069: 21070: 21071: 21072: 21073: 21074: 21075: 21076: 21077: 21078: 21079: 21080: 21081: 21082: 21083: 21084: 21085: 21086: 21087: 21088: 21089: 21090: 21091: 21092: 21093: 21094: 21095: 21096: 21097: 21098: 21099: 21100: 21101: 21102: 21103: 21104: 21105: 21106: 21107: 21108: 21109: 21110: 21111: 21112: 21113: 21114: 21115: 21116: 21117: 21118: 21119: 21120: 21121: 21122: 21123: 21124: 21125: 21126: 21127: 21128: 21129: 21130: 21131: 21132: 21133: 21134: 21135: 21136: 21137: 21138: 21139: 21140: 21141: 21142: 21143: 21144: 21145: 21146: 21147: 21148: 21149: 21150: 21151: 21152: 21153: 21154: 21155: 21156: 21157: 21158: 21159: 21160: 21161: 21162: 21163: 21164: 21165: 21166: 21167: 21168: 21169: 21170: 21171: 21172: 21173: 21174: 21175: 21176: 21177: 21178: 21179: 21180: 21181: 21182: 21183: 21184: 21185: 21186: 21187: 21188: 21189: 21190: 21191: 21192: 21193: 21194: 21195: 21196: 21197: 21198: 21199: 21200: 21201: 21202: 21203: 21204: 21205: 21206: 21207: 21208: 21209: 21210: 21211: 21212: 21213: 21214: 21215: 21216: 21217: 21218: 21219: 21220: 21221: 21222: 21223: 21224: 21225: 21226: 21227: 21228: 21229: 21230: 21231: 21232: 21233: 21234: 21235: 21236: 21237: 21238: 21239: 21240: 21241: 21242: 21243: 21244: 21245: 21246: 21247: 21248: 21249: 21250: 21251: 21252: 21253: 21254: 21255: 21256: 21257: 21258: 21259: 21260: 21261: 21262: 21263: 21264: 21265: 21266: 21267: 21268: 21269: 21270: 21271: 21272: 21273: 21274: 21275: 21276: 21277: 21278: 21279: 21280: 21281: 21282: 21283: 21284: 21285: 21286: 21287: 21288: 21289: 21290: 21291: 21292: 21293: 21294: 21295: 21296: 21297: 21298: 21299: 21300: 21301: 21302: 21303: 21304: 21305: 21306: 21307: 21308: 21309: 21310: 21311: 21312: 21313: 21314: 21315: 21316: 21317: 21318: 21319: 21320: 21321: 21322: 21323: 21324: 21325: 21326: 21327: 21328: 21329: 21330: 21331: 21332: 21333: 21334: 21335: 21336: 21337: 21338: 21339: 21340: 21341: 21342: 21343: 21344: 21345: 21346: 21347: 21348: 21349: 21350: 21351: 21352: 21353: 21354: 21355: 21356: 21357: 21358: 21359: 21360: 21361: 21362: 21363: 21364: 21365: 21366: 21367: 21368: 21369: 21370: 21371: 21372: 21373: 21374: 21375: 21376: 21377: 21378: 21379: 21380: 21381: 21382: 21383: 21384: 21385: 21386: 21387: 21388: 21389: 21390: 21391: 21392: 21393: 21394: 21395: 21396: 21397: 21398: 21399: 21400: 21401: 21402: 21403: 21404: 21405: 21406: 21407: 21408: 21409: 21410: 21411: 21412: 21413: 21414: 21415: 21416: 21417: 21418: 21419: 21420: 21421: 21422: 21423: 21424: 21425: 21426: 21427: 21428: 21429: 21430: 21431: 21432: 21433: 21434: 21435: 21436: 21437: 21438: 21439: 21440: 21441: 21442: 21443: 21444: 21445: 21446: 21447: 21448: 21449: 21450: 21451: 21452: 21453: 21454: 21455: 21456: 21457: 21458: 21459: 21460: 21461: 21462: 21463: 21464: 21465: 21466: 21467: 21468: 21469: 21470: 21471: 21472: 21473: 21474: 21475: 21476: 21477: 21478: 21479: 21480: 21481: 21482: 21483: 21484: 21485: 21486: 21487: 21488: 21489: 21490: 21491: 21492: 21493: 21494: 21495: 21496: 21497: 21498: 21499: 21500: 21501: 21502: 21503: 21504: 21505: 21506: 21507: 21508: 21509: 21510: 21511: 21512: 21513: 21514: 21515: 21516: 21517: 21518: 21519: 21520: 21521: 21522: 21523: 21524: 21525: 21526: 21527: 21528: 21529: 21530: 21531: 21532: 21533: 21534: 21535: 21536: 21537: 21538: 21539: 21540: 21541: 21542: 21543: 21544: 21545: 21546: 21547: 21548: 21549: 21550: 21551: 21552: 21553: 21554: 21555: 21556: 21557: 21558: 21559: 21560: 21561: 21562: 21563: 21564: 21565: 21566: 21567: 21568: 21569: 21570: 21571: 21572: 21573: 21574: 21575: 21576: 21577: 21578: 21579: 21580: 21581: 21582: 21583: 21584: 21585: 21586: 21587: 21588: 21589: 21590: 21591: 21592: 21593: 21594: 21595: 21596: 21597: 21598: 21599: 21600: 21601: 21602: 21603: 21604: 21605: 21606: 21607: 21608: 21609: 21610: 21611: 21612: 21613: 21614: 21615: 21616: 21617: 21618: 21619: 21620: 21621: 21622: 21623: 21624: 21625: 21626: 21627: 21628: 21629: 21630: 21631: 21632: 21633: 21634: 21635: 21636: 21637: 21638: 21639: 21640: 21641: 21642: 21643: 21644: 21645: 21646: 21647: 21648: 21649: 21650: 21651: 21652: 21653: 21654: 21655: 21656: 21657: 21658: 21659: 21660: 21661: 21662: 21663: 21664: 21665: 21666: 21667: 21668: 21669: 21670: 21671: 21672: 21673: 21674: 21675: 21676: 21677: 21678: 21679: 21680: 21681: 21682: 21683: 21684: 21685: 21686: 21687: 21688: 21689: 21690: 21691: 21692: 21693: 21694: 21695: 21696: 21697: 21698: 21699: 21700: 21701: 21702: 21703: 21704: 21705: 21706: 21707: 21708: 21709: 21710: 21711: 21712: 21713: 21714: 21715: 21716: 21717: 21718: 21719: 21720: 21721: 21722: 21723: 21724: 21725: 21726: 21727: 21728: 21729: 21730: 21731: 21732: 21733: 21734: 21735: 21736: 21737: 21738: 21739: 21740: 21741: 21742: 21743: 21744: 21745: 21746: 21747: 21748: 21749: 21750: 21751: 21752: 21753: 21754: 21755: 21756: 21757: 21758: 21759: 21760: 21761: 21762: 21763: 21764: 21765: 21766: 21767: 21768: 21769: 21770: 21771: 21772: 21773: 21774: 21775: 21776: 21777: 21778: 21779: 21780: 21781: 21782: 21783: 21784: 21785: 21786: 21787: 21788: 21789: 21790: 21791: 21792: 21793: 21794: 21795: 21796: 21797: 21798: 21799: 21800: 21801: 21802: 21803: 21804: 21805: 21806: 21807: 21808: 21809: 21810: 21811: 21812: 21813: 21814: 21815: 21816: 21817: 21818: 21819: 21820: 21821: 21822: 21823: 21824: 21825: 21826: 21827: 21828: 21829: 21830: 21831: 21832: 21833: 21834: 21835: 21836: 21837: 21838: 21839: 21840: 21841: 21842: 21843: 21844: 21845: 21846: 21847: 21848: 21849: 21850: 21851: 21852: 21853: 21854: 21855: 21856: 21857: 21858: 21859: 21860: 21861: 21862: 21863: 21864: 21865: 21866: 21867: 21868: 21869: 21870: 21871: 21872: 21873: 21874: 21875: 21876: 21877: 21878: 21879: 21880: 21881: 21882: 21883: 21884: 21885: 21886: 21887: 21888: 21889: 21890: 21891: 21892: 21893: 21894: 21895: 21896: 21897: 21898: 21899: 21900: 21901: 21902: 21903: 21904: 21905: 21906: 21907: 21908: 21909: 21910: 21911: 21912: 21913: 21914: 21915: 21916: 21917: 21918: 21919: 21920: 21921: 21922: 21923: 21924: 21925: 21926: 21927: 21928: 21929: 21930: 21931: 21932: 21933: 21934: 21935: 21936: 21937: 21938: 21939: 21940: 21941: 21942: 21943: 21944: 21945: 21946: 21947: 21948: 21949: 21950: 21951: 21952: 21953: 21954: 21955: 21956: 21957: 21958: 21959: 21960: 21961: 21962: 21963: 21964: 21965: 21966: 21967: 21968: 21969: 21970: 21971: 21972: 21973: 21974: 21975: 21976: 21977: 21978: 21979: 21980: 21981: 21982: 21983: 21984: 21985: 21986: 21987: 21988: 21989: 21990: 21991: 21992: 21993: 21994: 21995: 21996: 21997: 21998: 21999: 22000: 22001: 22002: 22003: 22004: 22005: 22006: 22007: 22008: 22009: 22010: 22011: 22012: 22013: 22014: 22015: 22016: 22017: 22018: 22019: 22020: 22021: 22022: 22023: 22024: 22025: 22026: 22027: 22028: 22029: 22030: 22031: 22032: 22033: 22034: 22035: 22036: 22037: 22038: 22039: 22040: 22041: 22042: 22043: 22044: 22045: 22046: 22047: 22048: 22049: 22050: 22051: 22052: 22053: 22054: 22055: 22056: 22057: 22058: 22059: 22060: 22061: 22062: 22063: 22064: 22065: 22066: 22067: 22068: 22069: 22070: 22071: 22072: 22073: 22074: 22075: 22076: 22077: 22078: 22079: 22080: 22081: 22082: 22083: 22084: 22085: 22086: 22087: 22088: 22089: 22090: 22091: 22092: 22093: 22094: 22095: 22096: 22097: 22098: 22099: 22100: 22101: 22102: 22103: 22104: 22105: 22106: 22107: 22108: 22109: 22110: 22111: 22112: 22113: 22114: 22115: 22116: 22117: 22118: 22119: 22120: 22121: 22122: 22123: 22124: 22125: 22126: 22127: 22128: 22129: 22130: 22131: 22132: 22133: 22134: 22135: 22136: 22137: 22138: 22139: 22140: 22141: 22142: 22143: 22144: 22145: 22146: 22147: 22148: 22149: 22150: 22151: 22152: 22153: 22154: 22155: 22156: 22157: 22158: 22159: 22160: 22161: 22162: 22163: 22164: 22165: 22166: 22167: 22168: 22169: 22170: 22171: 22172: 22173: 22174: 22175: 22176: 22177: 22178: 22179: 22180: 22181: 22182: 22183: 22184: 22185: 22186: 22187: 22188: 22189: 22190: 22191: 22192: 22193: 22194: 22195: 22196: 22197: 22198: 22199: 22200: 22201: 22202: 22203: 22204: 22205: 22206: 22207: 22208: 22209: 22210: 22211: 22212: 22213: 22214: 22215: 22216: 22217: 22218: 22219: 22220: 22221: 22222: 22223: 22224: 22225: 22226: 22227: 22228: 22229: 22230: 22231: 22232: 22233: 22234: 22235: 22236: 22237: 22238: 22239: 22240: 22241: 22242: 22243: 22244: 22245: 22246: 22247: 22248: 22249: 22250: 22251: 22252: 22253: 22254: 22255: 22256: 22257: 22258: 22259: 22260: 22261: 22262: 22263: 22264: 22265: 22266: 22267: 22268: 22269: 22270: 22271: 22272: 22273: 22274: 22275: 22276: 22277: 22278: 22279: 22280: 22281: 22282: 22283: 22284: 22285: 22286: 22287: 22288: 22289: 22290: 22291: 22292: 22293: 22294: 22295: 22296: 22297: 22298: 22299: 22300: 22301: 22302: 22303: 22304: 22305: 22306: 22307: 22308: 22309: 22310: 22311: 22312: 22313: 22314: 22315: 22316: 22317: 22318: 22319: 22320: 22321: 22322: 22323: 22324: 22325: 22326: 22327: 22328: 22329: 22330: 22331: 22332: 22333: 22334: 22335: 22336: 22337: 22338: 22339: 22340: 22341: 22342: 22343: 22344: 22345: 22346: 22347: 22348: 22349: 22350: 22351: 22352: 22353: 22354: 22355: 22356: 22357: 22358: 22359: 22360: 22361: 22362: 22363: 22364: 22365: 22366: 22367: 22368: 22369: 22370: 22371: 22372: 22373: 22374: 22375: 22376: 22377: 22378: 22379: 22380: 22381: 22382: 22383: 22384: 22385: 22386: 22387: 22388: 22389: 22390: 22391: 22392: 22393: 22394: 22395: 22396: 22397: 22398: 22399: 22400: 22401: 22402: 22403: 22404: 22405: 22406: 22407: 22408: 22409: 22410: 22411: 22412: 22413: 22414: 22415: 22416: 22417: 22418: 22419: 22420: 22421: 22422: 22423: 22424: 22425: 22426: 22427: 22428: 22429: 22430: 22431: 22432: 22433: 22434: 22435: 22436: 22437: 22438: 22439: 22440: 22441: 22442: 22443: 22444: 22445: 22446: 22447: 22448: 22449: 22450: 22451: 22452: 22453: 22454: 22455: 22456: 22457: 22458: 22459: 22460: 22461: 22462: 22463: 22464: 22465: 22466: 22467: 22468: 22469: 22470: 22471: 22472: 22473: 22474: 22475: 22476: 22477: 22478: 22479: 22480: 22481: 22482: 22483: 22484: 22485: 22486: 22487: 22488: 22489: 22490: 22491: 22492: 22493: 22494: 22495: 22496: 22497: 22498: 22499: 22500: 22501: 22502: 22503: 22504: 22505: 22506: 22507: 22508: 22509: 22510: 22511: 22512: 22513: 22514: 22515: 22516: 22517: 22518: 22519: 22520: 22521: 22522: 22523: 22524: 22525: 22526: 22527: 22528: 22529: 22530: 22531: 22532: 22533: 22534: 22535: 22536: 22537: 22538: 22539: 22540: 22541: 22542: 22543: 22544: 22545: 22546: 22547: 22548: 22549: 22550: 22551: 22552: 22553: 22554: 22555: 22556: 22557: 22558: 22559: 22560: 22561: 22562: 22563: 22564: 22565: 22566: 22567: 22568: 22569: 22570: 22571: 22572: 22573: 22574: 22575: 22576: 22577: 22578: 22579: 22580: 22581: 22582: 22583: 22584: 22585: 22586: 22587: 22588: 22589: 22590: 22591: 22592: 22593: 22594: 22595: 22596: 22597: 22598: 22599: 22600: 22601: 22602: 22603: 22604: 22605: 22606: 22607: 22608: 22609: 22610: 22611: 22612: 22613: 22614: 22615: 22616: 22617: 22618: 22619: 22620: 22621: 22622: 22623: 22624: 22625: 22626: 22627: 22628: 22629: 22630: 22631: 22632: 22633: 22634: 22635: 22636: 22637: 22638: 22639: 22640: 22641: 22642: 22643: 22644: 22645: 22646: 22647: 22648: 22649: 22650: 22651: 22652: 22653: 22654: 22655: 22656: 22657: 22658: 22659: 22660: 22661: 22662: 22663: 22664: 22665: 22666: 22667: 22668: 22669: 22670: 22671: 22672: 22673: 22674: 22675: 22676: 22677: 22678: 22679: 22680: 22681: 22682: 22683: 22684: 22685: 22686: 22687: 22688: 22689: 22690: 22691: 22692: 22693: 22694: 22695: 22696: 22697: 22698: 22699: 22700: 22701: 22702: 22703: 22704: 22705: 22706: 22707: 22708: 22709: 22710: 22711: 22712: 22713: 22714: 22715: 22716: 22717: 22718: 22719: 22720: 22721: 22722: 22723: 22724: 22725: 22726: 22727: 22728: 22729: 22730: 22731: 22732: 22733: 22734: 22735: 22736: 22737: 22738: 22739: 22740: 22741: 22742: 22743: 22744: 22745: 22746: 22747: 22748: 22749: 22750: 22751: 22752: 22753: 22754: 22755: 22756: 22757: 22758: 22759: 22760: 22761: 22762: 22763: 22764: 22765: 22766: 22767: 22768: 22769: 22770: 22771: 22772: 22773: 22774: 22775: 22776: 22777: 22778: 22779: 22780: 22781: 22782: 22783: 22784: 22785: 22786: 22787: 22788: 22789: 22790: 22791: 22792: 22793: 22794: 22795: 22796: 22797: 22798: 22799: 22800: 22801: 22802: 22803: 22804: 22805: 22806: 22807: 22808: 22809: 22810: 22811: 22812: 22813: 22814: 22815: 22816: 22817: 22818: 22819: 22820: 22821: 22822: 22823: 22824: 22825: 22826: 22827: 22828: 22829: 22830: 22831: 22832: 22833: 22834: 22835: 22836: 22837: 22838: 22839: 22840: 22841: 22842: 22843: 22844: 22845: 22846: 22847: 22848: 22849: 22850: 22851: 22852: 22853: 22854: 22855: 22856: 22857: 22858: 22859: 22860: 22861: 22862: 22863: 22864: 22865: 22866: 22867: 22868: 22869: 22870: 22871: 22872: 22873: 22874: 22875: 22876: 22877: 22878: 22879: 22880: 22881: 22882: 22883: 22884: 22885: 22886: 22887: 22888: 22889: 22890: 22891: 22892: 22893: 22894: 22895: 22896: 22897: 22898: 22899: 22900: 22901: 22902: 22903: 22904: 22905: 22906: 22907: 22908: 22909: 22910: 22911: 22912: 22913: 22914: 22915: 22916: 22917: 22918: 22919: 22920: 22921: 22922: 22923: 22924: 22925: 22926: 22927: 22928: 22929: 22930: 22931: 22932: 22933: 22934: 22935: 22936: 22937: 22938: 22939: 22940: 22941: 22942: 22943: 22944: 22945: 22946: 22947: 22948: 22949: 22950: 22951: 22952: 22953: 22954: 22955: 22956: 22957: 22958: 22959: 22960: 22961: 22962: 22963: 22964: 22965: 22966: 22967: 22968: 22969: 22970: 22971: 22972: 22973: 22974: 22975: 22976: 22977: 22978: 22979: 22980: 22981: 22982: 22983: 22984: 22985: 22986: 22987: 22988: 22989: 22990: 22991: 22992: 22993: 22994: 22995: 22996: 22997: 22998: 22999: 23000: 23001: 23002: 23003: 23004: 23005: 23006: 23007: 23008: 23009: 23010: 23011: 23012: 23013: 23014: 23015: 23016: 23017: 23018: 23019: 23020: 23021: 23022: 23023: 23024: 23025: 23026: 23027: 23028: 23029: 23030: 23031: 23032: 23033: 23034: 23035: 23036: 23037: 23038: 23039: 23040: 23041: 23042: 23043: 23044: 23045: 23046: 23047: 23048: 23049: 23050: 23051: 23052: 23053: 23054: 23055: 23056: 23057: 23058: 23059: 23060: 23061: 23062: 23063: 23064: 23065: 23066: 23067: 23068: 23069: 23070: 23071: 23072: 23073: 23074: 23075: 23076: 23077: 23078: 23079: 23080: 23081: 23082: 23083: 23084: 23085: 23086: 23087: 23088: 23089: 23090: 23091: 23092: 23093: 23094: 23095: 23096: 23097: 23098: 23099: 23100: 23101: 23102: 23103: 23104: 23105: 23106: 23107: 23108: 23109: 23110: 23111: 23112: 23113: 23114: 23115: 23116: 23117: 23118: 23119: 23120: 23121: 23122: 23123: 23124: 23125: 23126: 23127: 23128: 23129: 23130: 23131: 23132: 23133: 23134: 23135: 23136: 23137: 23138: 23139: 23140: 23141: 23142: 23143: 23144: 23145: 23146: 23147: 23148: 23149: 23150: 23151: 23152: 23153: 23154: 23155: 23156: 23157: 23158: 23159: 23160: 23161: 23162: 23163: 23164: 23165: 23166: 23167: 23168: 23169: 23170: 23171: 23172: 23173: 23174: 23175: 23176: 23177: 23178: 23179: 23180: 23181: 23182: 23183: 23184: 23185: 23186: 23187: 23188: 23189: 23190: 23191: 23192: 23193: 23194: 23195: 23196: 23197: 23198: 23199: 23200: 23201: 23202: 23203: 23204: 23205: 23206: 23207: 23208: 23209: 23210: 23211: 23212: 23213: 23214: 23215: 23216: 23217: 23218: 23219: 23220: 23221: 23222: 23223: 23224: 23225: 23226: 23227: 23228: 23229: 23230: 23231: 23232: 23233: 23234: 23235: 23236: 23237: 23238: 23239: 23240: 23241: 23242: 23243: 23244: 23245: 23246: 23247: 23248: 23249: 23250: 23251: 23252: 23253: 23254: 23255: 23256: 23257: 23258: 23259: 23260: 23261: 23262: 23263: 23264: 23265: 23266: 23267: 23268: 23269: 23270: 23271: 23272: 23273: 23274: 23275: 23276: 23277: 23278: 23279: 23280: 23281: 23282: 23283: 23284: 23285: 23286: 23287: 23288: 23289: 23290: 23291: 23292: 23293: 23294: 23295: 23296: 23297: 23298: 23299: 23300: 23301: 23302: 23303: 23304: 23305: 23306: 23307: 23308: 23309: 23310: 23311: 23312: 23313: 23314: 23315: 23316: 23317: 23318: 23319: 23320: 23321: 23322: 23323: 23324: 23325: 23326: 23327: 23328: 23329: 23330: 23331: 23332: 23333: 23334: 23335: 23336: 23337: 23338: 23339: 23340: 23341: 23342: 23343: 23344: 23345: 23346: 23347: 23348: 23349: 23350: 23351: 23352: 23353: 23354: 23355: 23356: 23357: 23358: 23359: 23360: 23361: 23362: 23363: 23364: 23365: 23366: 23367: 23368: 23369: 23370: 23371: 23372: 23373: 23374: 23375: 23376: 23377: 23378: 23379: 23380: 23381: 23382: 23383: 23384: 23385: 23386: 23387: 23388: 23389: 23390: 23391: 23392: 23393: 23394: 23395: 23396: 23397: 23398: 23399: 23400: 23401: 23402: 23403: 23404: 23405: 23406: 23407: 23408: 23409: 23410: 23411: 23412: 23413: 23414: 23415: 23416: 23417: 23418: 23419: 23420: 23421: 23422: 23423: 23424: 23425: 23426: 23427: 23428: 23429: 23430: 23431: 23432: 23433: 23434: 23435: 23436: 23437: 23438: 23439: 23440: 23441: 23442: 23443: 23444: 23445: 23446: 23447: 23448: 23449: 23450: 23451: 23452: 23453: 23454: 23455: 23456: 23457: 23458: 23459: 23460: 23461: 23462: 23463: 23464: 23465: 23466: 23467: 23468: 23469: 23470: 23471: 23472: 23473: 23474: 23475: 23476: 23477: 23478: 23479: 23480: 23481: 23482: 23483: 23484: 23485: 23486: 23487: 23488: 23489: 23490: 23491: 23492: 23493: 23494: 23495: 23496: 23497: 23498: 23499: 23500: 23501: 23502: 23503: 23504: 23505: 23506: 23507: 23508: 23509: 23510: 23511: 23512: 23513: 23514: 23515: 23516: 23517: 23518: 23519: 23520: 23521: 23522: 23523: 23524: 23525: 23526: 23527: 23528: 23529: 23530: 23531: 23532: 23533: 23534: 23535: 23536: 23537: 23538: 23539: 23540: 23541: 23542: 23543: 23544: 23545: 23546: 23547: 23548: 23549: 23550: 23551: 23552: 23553: 23554: 23555: 23556: 23557: 23558: 23559: 23560: 23561: 23562: 23563: 23564: 23565: 23566: 23567: 23568: 23569: 23570: 23571: 23572: 23573: 23574: 23575: 23576: 23577: 23578: 23579: 23580: 23581: 23582: 23583: 23584: 23585: 23586: 23587: 23588: 23589: 23590: 23591: 23592: 23593: 23594: 23595: 23596: 23597: 23598: 23599: 23600: 23601: 23602: 23603: 23604: 23605: 23606: 23607: 23608: 23609: 23610: 23611: 23612: 23613: 23614: 23615: 23616: 23617: 23618: 23619: 23620: 23621: 23622: 23623: 23624: 23625: 23626: 23627: 23628: 23629: 23630: 23631: 23632: 23633: 23634: 23635: 23636: 23637: 23638: 23639: 23640: 23641: 23642: 23643: 23644: 23645: 23646: 23647: 23648: 23649: 23650: 23651: 23652: 23653: 23654: 23655: 23656: 23657: 23658: 23659: 23660: 23661: 23662: 23663: 23664: 23665: 23666: 23667: 23668: 23669: 23670: 23671: 23672: 23673: 23674: 23675: 23676: 23677: 23678: 23679: 23680: 23681: 23682: 23683: 23684: 23685: 23686: 23687: 23688: 23689: 23690: 23691: 23692: 23693: 23694: 23695: 23696: 23697: 23698: 23699: 23700: 23701: 23702: 23703: 23704: 23705: 23706: 23707: 23708: 23709: 23710: 23711: 23712: 23713: 23714: 23715: 23716: 23717: 23718: 23719: 23720: 23721: 23722: 23723: 23724: 23725: 23726: 23727: 23728: 23729: 23730: 23731: 23732: 23733: 23734: 23735: 23736: 23737: 23738: 23739: 23740: 23741: 23742: 23743: 23744: 23745: 23746: 23747: 23748: 23749: 23750: 23751: 23752: 23753: 23754: 23755: 23756: 23757: 23758: 23759: 23760: 23761: 23762: 23763: 23764: 23765: 23766: 23767: 23768: 23769: 23770: 23771: 23772: 23773: 23774: 23775: 23776: 23777: 23778: 23779: 23780: 23781: 23782: 23783: 23784: 23785: 23786: 23787: 23788: 23789: 23790: 23791: 23792: 23793: 23794: 23795: 23796: 23797: 23798: 23799: 23800: 23801: 23802: 23803: 23804: 23805: 23806: 23807: 23808: 23809: 23810: 23811: 23812: 23813: 23814: 23815: 23816: 23817: 23818: 23819: 23820: 23821: 23822: 23823: 23824: 23825: 23826: 23827: 23828: 23829: 23830: 23831: 23832: 23833: 23834: 23835: 23836: 23837: 23838: 23839: 23840: 23841: 23842: 23843: 23844: 23845: 23846: 23847: 23848: 23849: 23850: 23851: 23852: 23853: 23854: 23855: 23856: 23857: 23858: 23859: 23860: 23861: 23862: 23863: 23864: 23865: 23866: 23867: 23868: 23869: 23870: 23871: 23872: 23873: 23874: 23875: 23876: 23877: 23878: 23879: 23880: 23881: 23882: 23883: 23884: 23885: 23886: 23887: 23888: 23889: 23890: 23891: 23892: 23893: 23894: 23895: 23896: 23897: 23898: 23899: 23900: 23901: 23902: 23903: 23904: 23905: 23906: 23907: 23908: 23909: 23910: 23911: 23912: 23913: 23914: 23915: 23916: 23917: 23918: 23919: 23920: 23921: 23922: 23923: 23924: 23925: 23926: 23927: 23928: 23929: 23930: 23931: 23932: 23933: 23934: 23935: 23936: 23937: 23938: 23939: 23940: 23941: 23942: 23943: 23944: 23945: 23946: 23947: 23948: 23949: 23950: 23951: 23952: 23953: 23954: 23955: 23956: 23957: 23958: 23959: 23960: 23961: 23962: 23963: 23964: 23965: 23966: 23967: 23968: 23969: 23970: 23971: 23972: 23973: 23974: 23975: 23976: 23977: 23978: 23979: 23980: 23981: 23982: 23983: 23984: 23985: 23986: 23987: 23988: 23989: 23990: 23991: 23992: 23993: 23994: 23995: 23996: 23997: 23998: 23999: 24000: 24001: 24002: 24003: 24004: 24005: 24006: 24007: 24008: 24009: 24010: 24011: 24012: 24013: 24014: 24015: 24016: 24017: 24018: 24019: 24020: 24021: 24022: 24023: 24024: 24025: 24026: 24027: 24028: 24029: 24030: 24031: 24032: 24033: 24034: 24035: 24036: 24037: 24038: 24039: 24040: 24041: 24042: 24043: 24044: 24045: 24046: 24047: 24048: 24049: 24050: 24051: 24052: 24053: 24054: 24055: 24056: 24057: 24058: 24059: 24060: 24061: 24062: 24063: 24064: 24065: 24066: 24067: 24068: 24069: 24070: 24071: 24072: 24073: 24074: 24075: 24076: 24077: 24078: 24079: 24080: 24081: 24082: 24083: 24084: 24085: 24086: 24087: 24088: 24089: 24090: 24091: 24092: 24093: 24094: 24095: 24096: 24097: 24098: 24099: 24100: 24101: 24102: 24103: 24104: 24105: 24106: 24107: 24108: 24109: 24110: 24111: 24112: 24113: 24114: 24115: 24116: 24117: 24118: 24119: 24120: 24121: 24122: 24123: 24124: 24125: 24126: 24127: 24128: 24129: 24130: 24131: 24132: 24133: 24134: 24135: 24136: 24137: 24138: 24139: 24140: 24141: 24142: 24143: 24144: 24145: 24146: 24147: 24148: 24149: 24150: 24151: 24152: 24153: 24154: 24155: 24156: 24157: 24158: 24159: 24160: 24161: 24162: 24163: 24164: 24165: 24166: 24167: 24168: 24169: 24170: 24171: 24172: 24173: 24174: 24175: 24176: 24177: 24178: 24179: 24180: 24181: 24182: 24183: 24184: 24185: 24186: 24187: 24188: 24189: 24190: 24191: 24192: 24193: 24194: 24195: 24196: 24197: 24198: 24199: 24200: 24201: 24202: 24203: 24204: 24205: 24206: 24207: 24208: 24209: 24210: 24211: 24212: 24213: 24214: 24215: 24216: 24217: 24218: 24219: 24220: 24221: 24222: 24223: 24224: 24225: 24226: 24227: 24228: 24229: 24230: 24231: 24232: 24233: 24234: 24235: 24236: 24237: 24238: 24239: 24240: 24241: 24242: 24243: 24244: 24245: 24246: 24247: 24248: 24249: 24250: 24251: 24252: 24253: 24254: 24255: 24256: 24257: 24258: 24259: 24260: 24261: 24262: 24263: 24264: 24265: 24266: 24267: 24268: 24269: 24270: 24271: 24272: 24273: 24274: 24275: 24276: 24277: 24278: 24279: 24280: 24281: 24282: 24283: 24284: 24285: 24286: 24287: 24288: 24289: 24290: 24291: 24292: 24293: 24294: 24295: 24296: 24297: 24298: 24299: 24300: 24301: 24302: 24303: 24304: 24305: 24306: 24307: 24308: 24309: 24310: 24311: 24312: 24313: 24314: 24315: 24316: 24317: 24318: 24319: 24320: 24321: 24322: 24323: 24324: 24325: 24326: 24327: 24328: 24329: 24330: 24331: 24332: 24333: 24334: 24335: 24336: 24337: 24338: 24339: 24340: 24341: 24342: 24343: 24344: 24345: 24346: 24347: 24348: 24349: 24350: 24351: 24352: 24353: 24354: 24355: 24356: 24357: 24358: 24359: 24360: 24361: 24362: 24363: 24364: 24365: 24366: 24367: 24368: 24369: 24370: 24371: 24372: 24373: 24374: 24375: 24376: 24377: 24378: 24379: 24380: 24381: 24382: 24383: 24384: 24385: 24386: 24387: 24388: 24389: 24390: 24391: 24392: 24393: 24394: 24395: 24396: 24397: 24398: 24399: 24400: 24401: 24402: 24403: 24404: 24405: 24406: 24407: 24408: 24409: 24410: 24411: 24412: 24413: 24414: 24415: 24416: 24417: 24418: 24419: 24420: 24421: 24422: 24423: 24424: 24425: 24426: 24427: 24428: 24429: 24430: 24431: 24432: 24433: 24434: 24435: 24436: 24437: 24438: 24439: 24440: 24441: 24442: 24443: 24444: 24445: 24446: 24447: 24448: 24449: 24450: 24451: 24452: 24453: 24454: 24455: 24456: 24457: 24458: 24459: 24460: 24461: 24462: 24463: 24464: 24465: 24466: 24467: 24468: 24469: 24470: 24471: 24472: 24473: 24474: 24475: 24476: 24477: 24478: 24479: 24480: 24481: 24482: 24483: 24484: 24485: 24486: 24487: 24488:
<?php
require_once(dirname(__FILE__).'/tcpdf_autoconfig.php');
require_once(dirname(__FILE__).'/include/tcpdf_font_data.php');
require_once(dirname(__FILE__).'/include/tcpdf_fonts.php');
require_once(dirname(__FILE__).'/include/tcpdf_colors.php');
require_once(dirname(__FILE__).'/include/tcpdf_images.php');
require_once(dirname(__FILE__).'/include/tcpdf_static.php');
class TCPDF {
protected $page;
protected $n;
protected $offsets = array();
protected $pageobjects = array();
protected $buffer;
protected $pages = array();
protected $state;
protected $compress;
protected $CurOrientation;
protected $pagedim = array();
protected $k;
protected $fwPt;
protected $fhPt;
protected $wPt;
protected $hPt;
protected $w;
protected $h;
protected $lMargin;
protected $rMargin;
protected $clMargin;
protected $crMargin;
protected $tMargin;
protected $bMargin;
protected $cell_padding = array('T' => 0, 'R' => 0, 'B' => 0, 'L' => 0);
protected $cell_margin = array('T' => 0, 'R' => 0, 'B' => 0, 'L' => 0);
protected $x;
protected $y;
protected $lasth;
protected $LineWidth;
protected $CoreFonts;
protected $fonts = array();
protected $FontFiles = array();
protected $diffs = array();
protected $images = array();
protected $svg_tag_depth = 0;
protected $PageAnnots = array();
protected $links = array();
protected $FontFamily;
protected $FontStyle;
protected $FontAscent;
protected $FontDescent;
protected $underline;
protected $overline;
protected $CurrentFont;
protected $FontSizePt;
protected $FontSize;
protected $DrawColor;
protected $FillColor;
protected $TextColor;
protected $ColorFlag;
protected $AutoPageBreak;
protected $PageBreakTrigger;
protected $InHeader = false;
protected $InFooter = false;
protected $ZoomMode;
protected $LayoutMode;
protected $docinfounicode = true;
protected $title = '';
protected $subject = '';
protected $author = '';
protected $keywords = '';
protected $creator = '';
protected $starting_page_number = 1;
protected $img_rb_x;
protected $img_rb_y;
protected $imgscale = 1;
protected $isunicode = false;
protected $PDFVersion = '1.7';
protected $header_xobjid = false;
protected $header_xobj_autoreset = false;
protected $header_margin;
protected $footer_margin;
protected $original_lMargin;
protected $original_rMargin;
protected $header_font;
protected $footer_font;
protected $l;
protected $barcode = false;
protected $print_header = true;
protected $print_footer = true;
protected $header_logo = '';
protected $header_logo_width = 30;
protected $header_title = '';
protected $header_string = '';
protected $header_text_color = array(0,0,0);
protected $header_line_color = array(0,0,0);
protected $footer_text_color = array(0,0,0);
protected $footer_line_color = array(0,0,0);
protected $txtshadow = array('enabled'=>false, 'depth_w'=>0, 'depth_h'=>0, 'color'=>false, 'opacity'=>1, 'blend_mode'=>'Normal');
protected $default_table_columns = 4;
protected $HREF = array();
protected $fontlist = array();
protected $fgcolor;
protected $listordered = array();
protected $listcount = array();
protected $listnum = 0;
protected $listindent = 0;
protected $listindentlevel = 0;
protected $bgcolor;
protected $tempfontsize = 10;
protected $lispacer = '';
protected $encoding = 'UTF-8';
protected $internal_encoding;
protected $rtl = false;
protected $tmprtl = false;
protected $encrypted;
protected $encryptdata = array();
protected $last_enc_key;
protected $last_enc_key_c;
protected $file_id;
protected $outlines = array();
protected $OutlineRoot;
protected $javascript = '';
protected $n_js;
protected $linethrough;
protected $ur = array();
protected $dpi = 72;
protected $newpagegroup = array();
protected $pagegroups = array();
protected $currpagegroup = 0;
protected $extgstates;
protected $jpeg_quality;
protected $cell_height_ratio = K_CELL_HEIGHT_RATIO;
protected $viewer_preferences;
protected $PageMode;
protected $gradients = array();
protected $intmrk = array();
protected $bordermrk = array();
protected $emptypagemrk = array();
protected $cntmrk = array();
protected $footerpos = array();
protected $footerlen = array();
protected $newline = true;
protected $endlinex = 0;
protected $linestyleWidth = '';
protected $linestyleCap = '0 J';
protected $linestyleJoin = '0 j';
protected $linestyleDash = '[] 0 d';
protected $openMarkedContent = false;
protected $htmlvspace = 0;
protected $spot_colors = array();
protected $lisymbol = '';
protected $epsmarker = 'x#!#EPS#!#x';
protected $transfmatrix = array();
protected $transfmatrix_key = 0;
protected $booklet = false;
protected $feps = 0.005;
protected $tagvspaces = array();
protected $customlistindent = -1;
protected $opencell = true;
protected $embeddedfiles = array();
protected $premode = false;
protected $transfmrk = array();
protected $htmlLinkColorArray = array(0, 0, 255);
protected $htmlLinkFontStyle = 'U';
protected $numpages = 0;
protected $pagelen = array();
protected $numimages = 0;
protected $imagekeys = array();
protected $bufferlen = 0;
protected $numfonts = 0;
protected $fontkeys = array();
protected $font_obj_ids = array();
protected $pageopen = array();
protected $default_monospaced_font = 'courier';
protected $objcopy;
protected $cache_file_length = array();
protected $thead = '';
protected $theadMargins = array();
protected $sign = false;
protected $signature_data = array();
protected $signature_max_length = 11742;
protected $signature_appearance = array('page' => 1, 'rect' => '0 0 0 0');
protected $empty_signature_appearance = array();
protected $tsa_timestamp = false;
protected $tsa_data = array();
protected $re_spaces = '/[^\S\xa0]/';
protected $re_space = array('p' => '[^\S\xa0]', 'm' => '');
protected $sig_obj_id = 0;
protected $page_obj_id = array();
protected $form_obj_id = array();
protected $default_form_prop = array('lineWidth'=>1, 'borderStyle'=>'solid', 'fillColor'=>array(255, 255, 255), 'strokeColor'=>array(128, 128, 128));
protected $js_objects = array();
protected $form_action = '';
protected $form_enctype = 'application/x-www-form-urlencoded';
protected $form_mode = 'post';
protected $annotation_fonts = array();
protected $radiobutton_groups = array();
protected $radio_groups = array();
protected $textindent = 0;
protected $start_transaction_page = 0;
protected $start_transaction_y = 0;
protected $inthead = false;
protected $columns = array();
protected $num_columns = 1;
protected $current_column = 0;
protected $column_start_page = 0;
protected $maxselcol = array('page' => 0, 'column' => 0);
protected $colxshift = array('x' => 0, 's' => array('H' => 0, 'V' => 0), 'p' => array('L' => 0, 'T' => 0, 'R' => 0, 'B' => 0));
protected $textrendermode = 0;
protected $textstrokewidth = 0;
protected $strokecolor;
protected $pdfunit = 'mm';
protected $tocpage = false;
protected $rasterize_vector_images = false;
protected $font_subsetting = true;
protected $default_graphic_vars = array();
protected $xobjects = array();
protected $inxobj = false;
protected $xobjid = '';
protected $font_stretching = 100;
protected $font_spacing = 0;
protected $page_regions = array();
protected $check_page_regions = true;
protected $pdflayers = array();
protected $dests = array();
protected $n_dests;
protected $efnames = array();
protected $svgdir = '';
protected $svgunit = 'px';
protected $svggradients = array();
protected $svggradientid = 0;
protected $svgdefsmode = false;
protected $svgdefs = array();
protected $svgclipmode = false;
protected $svgclippaths = array();
protected $svgcliptm = array();
protected $svgclipid = 0;
protected $svgtext = '';
protected $svgtextmode = array();
protected $svgstyles = array(array(
'alignment-baseline' => 'auto',
'baseline-shift' => 'baseline',
'clip' => 'auto',
'clip-path' => 'none',
'clip-rule' => 'nonzero',
'color' => 'black',
'color-interpolation' => 'sRGB',
'color-interpolation-filters' => 'linearRGB',
'color-profile' => 'auto',
'color-rendering' => 'auto',
'cursor' => 'auto',
'direction' => 'ltr',
'display' => 'inline',
'dominant-baseline' => 'auto',
'enable-background' => 'accumulate',
'fill' => 'black',
'fill-opacity' => 1,
'fill-rule' => 'nonzero',
'filter' => 'none',
'flood-color' => 'black',
'flood-opacity' => 1,
'font' => '',
'font-family' => 'helvetica',
'font-size' => 'medium',
'font-size-adjust' => 'none',
'font-stretch' => 'normal',
'font-style' => 'normal',
'font-variant' => 'normal',
'font-weight' => 'normal',
'glyph-orientation-horizontal' => '0deg',
'glyph-orientation-vertical' => 'auto',
'image-rendering' => 'auto',
'kerning' => 'auto',
'letter-spacing' => 'normal',
'lighting-color' => 'white',
'marker' => '',
'marker-end' => 'none',
'marker-mid' => 'none',
'marker-start' => 'none',
'mask' => 'none',
'opacity' => 1,
'overflow' => 'auto',
'pointer-events' => 'visiblePainted',
'shape-rendering' => 'auto',
'stop-color' => 'black',
'stop-opacity' => 1,
'stroke' => 'none',
'stroke-dasharray' => 'none',
'stroke-dashoffset' => 0,
'stroke-linecap' => 'butt',
'stroke-linejoin' => 'miter',
'stroke-miterlimit' => 4,
'stroke-opacity' => 1,
'stroke-width' => 1,
'text-anchor' => 'start',
'text-decoration' => 'none',
'text-rendering' => 'auto',
'unicode-bidi' => 'normal',
'visibility' => 'visible',
'word-spacing' => 'normal',
'writing-mode' => 'lr-tb',
'text-color' => 'black',
'transfmatrix' => array(1, 0, 0, 1, 0, 0)
));
protected $force_srgb = false;
protected $pdfa_mode = false;
protected $doc_creation_timestamp;
protected $doc_modification_timestamp;
protected $custom_xmp = '';
protected $overprint = array('OP' => false, 'op' => false, 'OPM' => 0);
protected $alpha = array('CA' => 1, 'ca' => 1, 'BM' => '/Normal', 'AIS' => false);
protected $page_boxes = array('MediaBox', 'CropBox', 'BleedBox', 'TrimBox', 'ArtBox');
protected $tcpdflink = true;
protected $gdgammacache = array();
public function __construct($orientation='P', $unit='mm', $format='A4', $unicode=true, $encoding='UTF-8', $diskcache=false, $pdfa=false) {
if (function_exists('mb_internal_encoding') AND mb_internal_encoding()) {
$this->internal_encoding = mb_internal_encoding();
mb_internal_encoding('ASCII');
}
$serformat = (is_array($format) ? json_encode($format) : $format);
$this->file_id = md5(TCPDF_STATIC::getRandomSeed('TCPDF'.$orientation.$unit.$serformat.$encoding));
$this->font_obj_ids = array();
$this->page_obj_id = array();
$this->form_obj_id = array();
$this->pdfa_mode = $pdfa;
$this->force_srgb = false;
$this->rtl = false;
$this->tmprtl = false;
$this->_dochecks();
$this->isunicode = $unicode;
$this->page = 0;
$this->transfmrk[0] = array();
$this->pagedim = array();
$this->n = 2;
$this->buffer = '';
$this->pages = array();
$this->state = 0;
$this->fonts = array();
$this->FontFiles = array();
$this->diffs = array();
$this->images = array();
$this->links = array();
$this->gradients = array();
$this->InFooter = false;
$this->lasth = 0;
$this->FontFamily = defined('PDF_FONT_NAME_MAIN')?PDF_FONT_NAME_MAIN:'helvetica';
$this->FontStyle = '';
$this->FontSizePt = 12;
$this->underline = false;
$this->overline = false;
$this->linethrough = false;
$this->DrawColor = '0 G';
$this->FillColor = '0 g';
$this->TextColor = '0 g';
$this->ColorFlag = false;
$this->pdflayers = array();
$this->encrypted = false;
$this->last_enc_key = '';
$this->CoreFonts = array(
'courier'=>'Courier',
'courierB'=>'Courier-Bold',
'courierI'=>'Courier-Oblique',
'courierBI'=>'Courier-BoldOblique',
'helvetica'=>'Helvetica',
'helveticaB'=>'Helvetica-Bold',
'helveticaI'=>'Helvetica-Oblique',
'helveticaBI'=>'Helvetica-BoldOblique',
'times'=>'Times-Roman',
'timesB'=>'Times-Bold',
'timesI'=>'Times-Italic',
'timesBI'=>'Times-BoldItalic',
'symbol'=>'Symbol',
'zapfdingbats'=>'ZapfDingbats'
);
$this->setPageUnit($unit);
$this->setPageFormat($format, $orientation);
$margin = 28.35 / $this->k;
$this->SetMargins($margin, $margin);
$this->clMargin = $this->lMargin;
$this->crMargin = $this->rMargin;
$cpadding = $margin / 10;
$this->setCellPaddings($cpadding, 0, $cpadding, 0);
$this->setCellMargins(0, 0, 0, 0);
$this->LineWidth = 0.57 / $this->k;
$this->linestyleWidth = sprintf('%F w', ($this->LineWidth * $this->k));
$this->linestyleCap = '0 J';
$this->linestyleJoin = '0 j';
$this->linestyleDash = '[] 0 d';
$this->SetAutoPageBreak(true, (2 * $margin));
$this->SetDisplayMode('fullwidth');
$this->SetCompression();
$this->setPDFVersion();
$this->tcpdflink = true;
$this->encoding = $encoding;
$this->HREF = array();
$this->getFontsList();
$this->fgcolor = array('R' => 0, 'G' => 0, 'B' => 0);
$this->strokecolor = array('R' => 0, 'G' => 0, 'B' => 0);
$this->bgcolor = array('R' => 255, 'G' => 255, 'B' => 255);
$this->extgstates = array();
$this->setTextShadow();
$this->sign = false;
$this->tsa_timestamp = false;
$this->tsa_data = array();
$this->signature_appearance = array('page' => 1, 'rect' => '0 0 0 0', 'name' => 'Signature');
$this->empty_signature_appearance = array();
$this->ur['enabled'] = false;
$this->ur['document'] = '/FullSave';
$this->ur['annots'] = '/Create/Delete/Modify/Copy/Import/Export';
$this->ur['form'] = '/Add/Delete/FillIn/Import/Export/SubmitStandalone/SpawnTemplate';
$this->ur['signature'] = '/Modify';
$this->ur['ef'] = '/Create/Delete/Modify/Import';
$this->ur['formex'] = '';
$this->jpeg_quality = 75;
TCPDF_FONTS::utf8Bidi(array(''), '', false, $this->isunicode, $this->CurrentFont);
$this->SetFont($this->FontFamily, $this->FontStyle, $this->FontSizePt);
$this->setHeaderFont(array($this->FontFamily, $this->FontStyle, $this->FontSizePt));
$this->setFooterFont(array($this->FontFamily, $this->FontStyle, $this->FontSizePt));
if ($this->isunicode AND (@preg_match('/\pL/u', 'a') == 1)) {
$this->setSpacesRE('/(?!\xa0)[\s\p{Z}]/u');
} else {
$this->setSpacesRE('/[^\S\xa0]/');
}
$this->default_form_prop = array('lineWidth'=>1, 'borderStyle'=>'solid', 'fillColor'=>array(255, 255, 255), 'strokeColor'=>array(128, 128, 128));
$this->doc_creation_timestamp = time();
$this->doc_modification_timestamp = $this->doc_creation_timestamp;
$this->default_graphic_vars = $this->getGraphicVars();
$this->header_xobj_autoreset = false;
$this->custom_xmp = '';
register_shutdown_function(array($this, '_destroy'), true);
}
public function __destruct() {
if (isset($this->internal_encoding) AND !empty($this->internal_encoding)) {
mb_internal_encoding($this->internal_encoding);
}
$this->_destroy(true);
}
public function setPageUnit($unit) {
$unit = strtolower($unit);
switch ($unit) {
case 'px':
case 'pt': {
$this->k = 1;
break;
}
case 'mm': {
$this->k = $this->dpi / 25.4;
break;
}
case 'cm': {
$this->k = $this->dpi / 2.54;
break;
}
case 'in': {
$this->k = $this->dpi;
break;
}
default : {
$this->Error('Incorrect unit: '.$unit);
break;
}
}
$this->pdfunit = $unit;
if (isset($this->CurOrientation)) {
$this->setPageOrientation($this->CurOrientation);
}
}
protected function setPageFormat($format, $orientation='P') {
if (!empty($format) AND isset($this->pagedim[$this->page])) {
unset($this->pagedim[$this->page]);
}
if (is_string($format)) {
$pf = TCPDF_STATIC::getPageSizeFromFormat($format);
$this->fwPt = $pf[0];
$this->fhPt = $pf[1];
} else {
if (isset($format['MediaBox'])) {
$this->pagedim = TCPDF_STATIC::setPageBoxes($this->page, 'MediaBox', $format['MediaBox']['llx'], $format['MediaBox']['lly'], $format['MediaBox']['urx'], $format['MediaBox']['ury'], false, $this->k, $this->pagedim);
$this->fwPt = (($format['MediaBox']['urx'] - $format['MediaBox']['llx']) * $this->k);
$this->fhPt = (($format['MediaBox']['ury'] - $format['MediaBox']['lly']) * $this->k);
} else {
if (isset($format[0]) AND is_numeric($format[0]) AND isset($format[1]) AND is_numeric($format[1])) {
$pf = array(($format[0] * $this->k), ($format[1] * $this->k));
} else {
if (!isset($format['format'])) {
$format['format'] = 'A4';
}
$pf = TCPDF_STATIC::getPageSizeFromFormat($format['format']);
}
$this->fwPt = $pf[0];
$this->fhPt = $pf[1];
$this->pagedim = TCPDF_STATIC::setPageBoxes($this->page, 'MediaBox', 0, 0, $this->fwPt, $this->fhPt, true, $this->k, $this->pagedim);
}
if (isset($format['CropBox'])) {
$this->pagedim = TCPDF_STATIC::setPageBoxes($this->page, 'CropBox', $format['CropBox']['llx'], $format['CropBox']['lly'], $format['CropBox']['urx'], $format['CropBox']['ury'], false, $this->k, $this->pagedim);
}
if (isset($format['BleedBox'])) {
$this->pagedim = TCPDF_STATIC::setPageBoxes($this->page, 'BleedBox', $format['BleedBox']['llx'], $format['BleedBox']['lly'], $format['BleedBox']['urx'], $format['BleedBox']['ury'], false, $this->k, $this->pagedim);
}
if (isset($format['TrimBox'])) {
$this->pagedim = TCPDF_STATIC::setPageBoxes($this->page, 'TrimBox', $format['TrimBox']['llx'], $format['TrimBox']['lly'], $format['TrimBox']['urx'], $format['TrimBox']['ury'], false, $this->k, $this->pagedim);
}
if (isset($format['ArtBox'])) {
$this->pagedim = TCPDF_STATIC::setPageBoxes($this->page, 'ArtBox', $format['ArtBox']['llx'], $format['ArtBox']['lly'], $format['ArtBox']['urx'], $format['ArtBox']['ury'], false, $this->k, $this->pagedim);
}
if (isset($format['BoxColorInfo'])) {
$this->pagedim[$this->page]['BoxColorInfo'] = $format['BoxColorInfo'];
}
if (isset($format['Rotate']) AND (($format['Rotate'] % 90) == 0)) {
$this->pagedim[$this->page]['Rotate'] = intval($format['Rotate']);
}
if (isset($format['PZ'])) {
$this->pagedim[$this->page]['PZ'] = floatval($format['PZ']);
}
if (isset($format['trans'])) {
if (isset($format['trans']['Dur'])) {
$this->pagedim[$this->page]['trans']['Dur'] = floatval($format['trans']['Dur']);
}
$stansition_styles = array('Split', 'Blinds', 'Box', 'Wipe', 'Dissolve', 'Glitter', 'R', 'Fly', 'Push', 'Cover', 'Uncover', 'Fade');
if (isset($format['trans']['S']) AND in_array($format['trans']['S'], $stansition_styles)) {
$this->pagedim[$this->page]['trans']['S'] = $format['trans']['S'];
$valid_effect = array('Split', 'Blinds');
$valid_vals = array('H', 'V');
if (isset($format['trans']['Dm']) AND in_array($format['trans']['S'], $valid_effect) AND in_array($format['trans']['Dm'], $valid_vals)) {
$this->pagedim[$this->page]['trans']['Dm'] = $format['trans']['Dm'];
}
$valid_effect = array('Split', 'Box', 'Fly');
$valid_vals = array('I', 'O');
if (isset($format['trans']['M']) AND in_array($format['trans']['S'], $valid_effect) AND in_array($format['trans']['M'], $valid_vals)) {
$this->pagedim[$this->page]['trans']['M'] = $format['trans']['M'];
}
$valid_effect = array('Wipe', 'Glitter', 'Fly', 'Cover', 'Uncover', 'Push');
if (isset($format['trans']['Di']) AND in_array($format['trans']['S'], $valid_effect)) {
if (((($format['trans']['Di'] == 90) OR ($format['trans']['Di'] == 180)) AND ($format['trans']['S'] == 'Wipe'))
OR (($format['trans']['Di'] == 315) AND ($format['trans']['S'] == 'Glitter'))
OR (($format['trans']['Di'] == 0) OR ($format['trans']['Di'] == 270))) {
$this->pagedim[$this->page]['trans']['Di'] = intval($format['trans']['Di']);
}
}
if (isset($format['trans']['SS']) AND ($format['trans']['S'] == 'Fly')) {
$this->pagedim[$this->page]['trans']['SS'] = floatval($format['trans']['SS']);
}
if (isset($format['trans']['B']) AND ($format['trans']['B'] === true) AND ($format['trans']['S'] == 'Fly')) {
$this->pagedim[$this->page]['trans']['B'] = 'true';
}
} else {
$this->pagedim[$this->page]['trans']['S'] = 'R';
}
if (isset($format['trans']['D'])) {
$this->pagedim[$this->page]['trans']['D'] = floatval($format['trans']['D']);
} else {
$this->pagedim[$this->page]['trans']['D'] = 1;
}
}
}
$this->setPageOrientation($orientation);
}
public function setPageOrientation($orientation, $autopagebreak='', $bottommargin='') {
if (!isset($this->pagedim[$this->page]['MediaBox'])) {
$this->pagedim = TCPDF_STATIC::setPageBoxes($this->page, 'MediaBox', 0, 0, $this->fwPt, $this->fhPt, true, $this->k, $this->pagedim);
}
if (!isset($this->pagedim[$this->page]['CropBox'])) {
$this->pagedim = TCPDF_STATIC::setPageBoxes($this->page, 'CropBox', $this->pagedim[$this->page]['MediaBox']['llx'], $this->pagedim[$this->page]['MediaBox']['lly'], $this->pagedim[$this->page]['MediaBox']['urx'], $this->pagedim[$this->page]['MediaBox']['ury'], true, $this->k, $this->pagedim);
}
if (!isset($this->pagedim[$this->page]['BleedBox'])) {
$this->pagedim = TCPDF_STATIC::setPageBoxes($this->page, 'BleedBox', $this->pagedim[$this->page]['CropBox']['llx'], $this->pagedim[$this->page]['CropBox']['lly'], $this->pagedim[$this->page]['CropBox']['urx'], $this->pagedim[$this->page]['CropBox']['ury'], true, $this->k, $this->pagedim);
}
if (!isset($this->pagedim[$this->page]['TrimBox'])) {
$this->pagedim = TCPDF_STATIC::setPageBoxes($this->page, 'TrimBox', $this->pagedim[$this->page]['CropBox']['llx'], $this->pagedim[$this->page]['CropBox']['lly'], $this->pagedim[$this->page]['CropBox']['urx'], $this->pagedim[$this->page]['CropBox']['ury'], true, $this->k, $this->pagedim);
}
if (!isset($this->pagedim[$this->page]['ArtBox'])) {
$this->pagedim = TCPDF_STATIC::setPageBoxes($this->page, 'ArtBox', $this->pagedim[$this->page]['CropBox']['llx'], $this->pagedim[$this->page]['CropBox']['lly'], $this->pagedim[$this->page]['CropBox']['urx'], $this->pagedim[$this->page]['CropBox']['ury'], true, $this->k, $this->pagedim);
}
if (!isset($this->pagedim[$this->page]['Rotate'])) {
$this->pagedim[$this->page]['Rotate'] = 0;
}
if (!isset($this->pagedim[$this->page]['PZ'])) {
$this->pagedim[$this->page]['PZ'] = 1;
}
if ($this->fwPt > $this->fhPt) {
$default_orientation = 'L';
} else {
$default_orientation = 'P';
}
$valid_orientations = array('P', 'L');
if (empty($orientation)) {
$orientation = $default_orientation;
} else {
$orientation = strtoupper($orientation[0]);
}
if (in_array($orientation, $valid_orientations) AND ($orientation != $default_orientation)) {
$this->CurOrientation = $orientation;
$this->wPt = $this->fhPt;
$this->hPt = $this->fwPt;
} else {
$this->CurOrientation = $default_orientation;
$this->wPt = $this->fwPt;
$this->hPt = $this->fhPt;
}
if ((abs($this->pagedim[$this->page]['MediaBox']['urx'] - $this->hPt) < $this->feps) AND (abs($this->pagedim[$this->page]['MediaBox']['ury'] - $this->wPt) < $this->feps)){
$this->pagedim = TCPDF_STATIC::swapPageBoxCoordinates($this->page, $this->pagedim);
}
$this->w = ($this->wPt / $this->k);
$this->h = ($this->hPt / $this->k);
if (TCPDF_STATIC::empty_string($autopagebreak)) {
if (isset($this->AutoPageBreak)) {
$autopagebreak = $this->AutoPageBreak;
} else {
$autopagebreak = true;
}
}
if (TCPDF_STATIC::empty_string($bottommargin)) {
if (isset($this->bMargin)) {
$bottommargin = $this->bMargin;
} else {
$bottommargin = 2 * 28.35 / $this->k;
}
}
$this->SetAutoPageBreak($autopagebreak, $bottommargin);
$this->pagedim[$this->page]['w'] = $this->wPt;
$this->pagedim[$this->page]['h'] = $this->hPt;
$this->pagedim[$this->page]['wk'] = $this->w;
$this->pagedim[$this->page]['hk'] = $this->h;
$this->pagedim[$this->page]['tm'] = $this->tMargin;
$this->pagedim[$this->page]['bm'] = $bottommargin;
$this->pagedim[$this->page]['lm'] = $this->lMargin;
$this->pagedim[$this->page]['rm'] = $this->rMargin;
$this->pagedim[$this->page]['pb'] = $autopagebreak;
$this->pagedim[$this->page]['or'] = $this->CurOrientation;
$this->pagedim[$this->page]['olm'] = $this->original_lMargin;
$this->pagedim[$this->page]['orm'] = $this->original_rMargin;
}
public function setSpacesRE($re='/[^\S\xa0]/') {
$this->re_spaces = $re;
$re_parts = explode('/', $re);
$this->re_space = array();
if (isset($re_parts[1]) AND !empty($re_parts[1])) {
$this->re_space['p'] = $re_parts[1];
} else {
$this->re_space['p'] = '[\s]';
}
if (isset($re_parts[2]) AND !empty($re_parts[2])) {
$this->re_space['m'] = $re_parts[2];
} else {
$this->re_space['m'] = '';
}
}
public function setRTL($enable, $resetx=true) {
$enable = $enable ? true : false;
$resetx = ($resetx AND ($enable != $this->rtl));
$this->rtl = $enable;
$this->tmprtl = false;
if ($resetx) {
$this->Ln(0);
}
}
public function getRTL() {
return $this->rtl;
}
public function setTempRTL($mode) {
$newmode = false;
switch (strtoupper($mode)) {
case 'LTR':
case 'L': {
if ($this->rtl) {
$newmode = 'L';
}
break;
}
case 'RTL':
case 'R': {
if (!$this->rtl) {
$newmode = 'R';
}
break;
}
case false:
default: {
$newmode = false;
break;
}
}
$this->tmprtl = $newmode;
}
public function isRTLTextDir() {
return ($this->rtl OR ($this->tmprtl == 'R'));
}
public function setLastH($h) {
$this->lasth = $h;
}
public function getCellHeight($fontsize, $padding=TRUE) {
$height = ($fontsize * $this->cell_height_ratio);
if ($padding) {
$height += ($this->cell_padding['T'] + $this->cell_padding['B']);
}
return round($height, 6);
}
public function resetLastH() {
$this->lasth = $this->getCellHeight($this->FontSize);
}
public function getLastH() {
return $this->lasth;
}
public function setImageScale($scale) {
$this->imgscale = $scale;
}
public function getImageScale() {
return $this->imgscale;
}
public function getPageDimensions($pagenum='') {
if (empty($pagenum)) {
$pagenum = $this->page;
}
return $this->pagedim[$pagenum];
}
public function getPageWidth($pagenum='') {
if (empty($pagenum)) {
return $this->w;
}
return $this->pagedim[$pagenum]['w'];
}
public function getPageHeight($pagenum='') {
if (empty($pagenum)) {
return $this->h;
}
return $this->pagedim[$pagenum]['h'];
}
public function getBreakMargin($pagenum='') {
if (empty($pagenum)) {
return $this->bMargin;
}
return $this->pagedim[$pagenum]['bm'];
}
public function getScaleFactor() {
return $this->k;
}
public function SetMargins($left, $top, $right=-1, $keepmargins=false) {
$this->lMargin = $left;
$this->tMargin = $top;
if ($right == -1) {
$right = $left;
}
$this->rMargin = $right;
if ($keepmargins) {
$this->original_lMargin = $this->lMargin;
$this->original_rMargin = $this->rMargin;
}
}
public function SetLeftMargin($margin) {
$this->lMargin = $margin;
if (($this->page > 0) AND ($this->x < $margin)) {
$this->x = $margin;
}
}
public function SetTopMargin($margin) {
$this->tMargin = $margin;
if (($this->page > 0) AND ($this->y < $margin)) {
$this->y = $margin;
}
}
public function SetRightMargin($margin) {
$this->rMargin = $margin;
if (($this->page > 0) AND ($this->x > ($this->w - $margin))) {
$this->x = $this->w - $margin;
}
}
public function SetCellPadding($pad) {
if ($pad >= 0) {
$this->cell_padding['L'] = $pad;
$this->cell_padding['T'] = $pad;
$this->cell_padding['R'] = $pad;
$this->cell_padding['B'] = $pad;
}
}
public function setCellPaddings($left='', $top='', $right='', $bottom='') {
if (($left !== '') AND ($left >= 0)) {
$this->cell_padding['L'] = $left;
}
if (($top !== '') AND ($top >= 0)) {
$this->cell_padding['T'] = $top;
}
if (($right !== '') AND ($right >= 0)) {
$this->cell_padding['R'] = $right;
}
if (($bottom !== '') AND ($bottom >= 0)) {
$this->cell_padding['B'] = $bottom;
}
}
public function getCellPaddings() {
return $this->cell_padding;
}
public function setCellMargins($left='', $top='', $right='', $bottom='') {
if (($left !== '') AND ($left >= 0)) {
$this->cell_margin['L'] = $left;
}
if (($top !== '') AND ($top >= 0)) {
$this->cell_margin['T'] = $top;
}
if (($right !== '') AND ($right >= 0)) {
$this->cell_margin['R'] = $right;
}
if (($bottom !== '') AND ($bottom >= 0)) {
$this->cell_margin['B'] = $bottom;
}
}
public function getCellMargins() {
return $this->cell_margin;
}
protected function adjustCellPadding($brd=0) {
if (empty($brd)) {
return;
}
if (is_string($brd)) {
$slen = strlen($brd);
$newbrd = array();
for ($i = 0; $i < $slen; ++$i) {
$newbrd[$brd[$i]] = true;
}
$brd = $newbrd;
} elseif (($brd === 1) OR ($brd === true) OR (is_numeric($brd) AND (intval($brd) > 0))) {
$brd = array('LRTB' => true);
}
if (!is_array($brd)) {
return;
}
$cp = $this->cell_padding;
if (isset($brd['mode'])) {
$mode = $brd['mode'];
unset($brd['mode']);
} else {
$mode = 'normal';
}
foreach ($brd as $border => $style) {
$line_width = $this->LineWidth;
if (is_array($style) AND isset($style['width'])) {
$line_width = $style['width'];
}
$adj = 0;
switch ($mode) {
case 'ext': {
$adj = 0;
break;
}
case 'int': {
$adj = $line_width;
break;
}
case 'normal':
default: {
$adj = ($line_width / 2);
break;
}
}
if ((strpos($border,'T') !== false) AND ($this->cell_padding['T'] < $adj)) {
$this->cell_padding['T'] = $adj;
}
if ((strpos($border,'R') !== false) AND ($this->cell_padding['R'] < $adj)) {
$this->cell_padding['R'] = $adj;
}
if ((strpos($border,'B') !== false) AND ($this->cell_padding['B'] < $adj)) {
$this->cell_padding['B'] = $adj;
}
if ((strpos($border,'L') !== false) AND ($this->cell_padding['L'] < $adj)) {
$this->cell_padding['L'] = $adj;
}
}
return array('T' => ($this->cell_padding['T'] - $cp['T']), 'R' => ($this->cell_padding['R'] - $cp['R']), 'B' => ($this->cell_padding['B'] - $cp['B']), 'L' => ($this->cell_padding['L'] - $cp['L']));
}
public function SetAutoPageBreak($auto, $margin=0) {
$this->AutoPageBreak = $auto ? true : false;
$this->bMargin = $margin;
$this->PageBreakTrigger = $this->h - $margin;
}
public function getAutoPageBreak() {
return $this->AutoPageBreak;
}
public function SetDisplayMode($zoom, $layout='SinglePage', $mode='UseNone') {
if (($zoom == 'fullpage') OR ($zoom == 'fullwidth') OR ($zoom == 'real') OR ($zoom == 'default') OR (!is_string($zoom))) {
$this->ZoomMode = $zoom;
} else {
$this->Error('Incorrect zoom display mode: '.$zoom);
}
$this->LayoutMode = TCPDF_STATIC::getPageLayoutMode($layout);
$this->PageMode = TCPDF_STATIC::getPageMode($mode);
}
public function SetCompression($compress=true) {
if (function_exists('gzcompress')) {
$this->compress = $compress ? true : false;
} else {
$this->compress = false;
}
}
public function setSRGBmode($mode=false) {
$this->force_srgb = $mode ? true : false;
}
public function SetDocInfoUnicode($unicode=true) {
$this->docinfounicode = $unicode ? true : false;
}
public function SetTitle($title) {
$this->title = $title;
}
public function SetSubject($subject) {
$this->subject = $subject;
}
public function SetAuthor($author) {
$this->author = $author;
}
public function SetKeywords($keywords) {
$this->keywords = $keywords;
}
public function SetCreator($creator) {
$this->creator = $creator;
}
public function Error($msg) {
$this->_destroy(true);
if (defined('K_TCPDF_THROW_EXCEPTION_ERROR') AND !K_TCPDF_THROW_EXCEPTION_ERROR) {
die('<strong>TCPDF ERROR: </strong>'.$msg);
} else {
throw new Exception('TCPDF ERROR: '.$msg);
}
}
public function Open() {
$this->state = 1;
}
public function Close() {
if ($this->state == 3) {
return;
}
if ($this->page == 0) {
$this->AddPage();
}
$this->endLayer();
if ($this->tcpdflink) {
$gvars = $this->getGraphicVars();
$this->setEqualColumns();
$this->lastpage(true);
$this->SetAutoPageBreak(false);
$this->x = 0;
$this->y = $this->h - (1 / $this->k);
$this->lMargin = 0;
$this->_outSaveGraphicsState();
$font = defined('PDF_FONT_NAME_MAIN')?PDF_FONT_NAME_MAIN:'helvetica';
$this->SetFont($font, '', 1);
$this->setTextRenderingMode(0, false, false);
$msg = "\x50\x6f\x77\x65\x72\x65\x64\x20\x62\x79\x20\x54\x43\x50\x44\x46\x20\x28\x77\x77\x77\x2e\x74\x63\x70\x64\x66\x2e\x6f\x72\x67\x29";
$lnk = "\x68\x74\x74\x70\x3a\x2f\x2f\x77\x77\x77\x2e\x74\x63\x70\x64\x66\x2e\x6f\x72\x67";
$this->Cell(0, 0, $msg, 0, 0, 'L', 0, $lnk, 0, false, 'D', 'B');
$this->_outRestoreGraphicsState();
$this->setGraphicVars($gvars);
}
$this->endPage();
$this->_enddoc();
$this->_destroy(false);
}
public function setPage($pnum, $resetmargins=false) {
if (($pnum == $this->page) AND ($this->state == 2)) {
return;
}
if (($pnum > 0) AND ($pnum <= $this->numpages)) {
$this->state = 2;
$oldpage = $this->page;
$this->page = $pnum;
$this->wPt = $this->pagedim[$this->page]['w'];
$this->hPt = $this->pagedim[$this->page]['h'];
$this->w = $this->pagedim[$this->page]['wk'];
$this->h = $this->pagedim[$this->page]['hk'];
$this->tMargin = $this->pagedim[$this->page]['tm'];
$this->bMargin = $this->pagedim[$this->page]['bm'];
$this->original_lMargin = $this->pagedim[$this->page]['olm'];
$this->original_rMargin = $this->pagedim[$this->page]['orm'];
$this->AutoPageBreak = $this->pagedim[$this->page]['pb'];
$this->CurOrientation = $this->pagedim[$this->page]['or'];
$this->SetAutoPageBreak($this->AutoPageBreak, $this->bMargin);
if ($resetmargins) {
$this->lMargin = $this->pagedim[$this->page]['olm'];
$this->rMargin = $this->pagedim[$this->page]['orm'];
$this->SetY($this->tMargin);
} else {
if ($this->pagedim[$this->page]['olm'] != $this->pagedim[$oldpage]['olm']) {
$deltam = $this->pagedim[$this->page]['olm'] - $this->pagedim[$this->page]['orm'];
$this->lMargin += $deltam;
$this->rMargin -= $deltam;
}
}
} else {
$this->Error('Wrong page number on setPage() function: '.$pnum);
}
}
public function lastPage($resetmargins=false) {
$this->setPage($this->getNumPages(), $resetmargins);
}
public function getPage() {
return $this->page;
}
public function getNumPages() {
return $this->numpages;
}
public function addTOCPage($orientation='', $format='', $keepmargins=false) {
$this->AddPage($orientation, $format, $keepmargins, true);
}
public function endTOCPage() {
$this->endPage(true);
}
public function AddPage($orientation='', $format='', $keepmargins=false, $tocpage=false) {
if ($this->inxobj) {
return;
}
if (!isset($this->original_lMargin) OR $keepmargins) {
$this->original_lMargin = $this->lMargin;
}
if (!isset($this->original_rMargin) OR $keepmargins) {
$this->original_rMargin = $this->rMargin;
}
$this->endPage();
$this->startPage($orientation, $format, $tocpage);
}
public function endPage($tocpage=false) {
if (($this->page == 0) OR ($this->numpages > $this->page) OR (!$this->pageopen[$this->page])) {
return;
}
$this->setFooter();
$this->_endpage();
$this->pageopen[$this->page] = false;
if ($tocpage) {
$this->tocpage = false;
}
}
public function startPage($orientation='', $format='', $tocpage=false) {
if ($tocpage) {
$this->tocpage = true;
}
if ($this->tocpage) {
$tmpoutlines = $this->outlines;
foreach ($tmpoutlines as $key => $outline) {
if (!$outline['f'] AND ($outline['p'] > $this->numpages)) {
$this->outlines[$key]['p'] = ($outline['p'] + 1);
}
}
$tmpdests = $this->dests;
foreach ($tmpdests as $key => $dest) {
if (!$dest['f'] AND ($dest['p'] > $this->numpages)) {
$this->dests[$key]['p'] = ($dest['p'] + 1);
}
}
$tmplinks = $this->links;
foreach ($tmplinks as $key => $link) {
if (!$link['f'] AND ($link['p'] > $this->numpages)) {
$this->links[$key]['p'] = ($link['p'] + 1);
}
}
}
if ($this->numpages > $this->page) {
$this->setPage($this->page + 1);
$this->SetY($this->tMargin);
return;
}
if ($this->state == 0) {
$this->Open();
}
++$this->numpages;
$this->swapMargins($this->booklet);
$gvars = $this->getGraphicVars();
$this->_beginpage($orientation, $format);
$this->pageopen[$this->page] = true;
$this->setGraphicVars($gvars);
$this->setPageMark();
$this->setHeader();
$this->setGraphicVars($gvars);
$this->setPageMark();
$this->setTableHeader();
$this->emptypagemrk[$this->page]= $this->pagelen[$this->page];
}
public function setPageMark() {
$this->intmrk[$this->page] = $this->pagelen[$this->page];
$this->bordermrk[$this->page] = $this->intmrk[$this->page];
$this->setContentMark();
}
protected function setContentMark($page=0) {
if ($page <= 0) {
$page = $this->page;
}
if (isset($this->footerlen[$page])) {
$this->cntmrk[$page] = $this->pagelen[$page] - $this->footerlen[$page];
} else {
$this->cntmrk[$page] = $this->pagelen[$page];
}
}
public function setHeaderData($ln='', $lw=0, $ht='', $hs='', $tc=array(0,0,0), $lc=array(0,0,0)) {
$this->header_logo = $ln;
$this->header_logo_width = $lw;
$this->header_title = $ht;
$this->header_string = $hs;
$this->header_text_color = $tc;
$this->header_line_color = $lc;
}
public function setFooterData($tc=array(0,0,0), $lc=array(0,0,0)) {
$this->footer_text_color = $tc;
$this->footer_line_color = $lc;
}
public function getHeaderData() {
$ret = array();
$ret['logo'] = $this->header_logo;
$ret['logo_width'] = $this->header_logo_width;
$ret['title'] = $this->header_title;
$ret['string'] = $this->header_string;
$ret['text_color'] = $this->header_text_color;
$ret['line_color'] = $this->header_line_color;
return $ret;
}
public function setHeaderMargin($hm=10) {
$this->header_margin = $hm;
}
public function getHeaderMargin() {
return $this->header_margin;
}
public function setFooterMargin($fm=10) {
$this->footer_margin = $fm;
}
public function getFooterMargin() {
return $this->footer_margin;
}
public function setPrintHeader($val=true) {
$this->print_header = $val ? true : false;
}
public function setPrintFooter($val=true) {
$this->print_footer = $val ? true : false;
}
public function getImageRBX() {
return $this->img_rb_x;
}
public function getImageRBY() {
return $this->img_rb_y;
}
public function resetHeaderTemplate() {
$this->header_xobjid = false;
}
public function setHeaderTemplateAutoreset($val=true) {
$this->header_xobj_autoreset = $val ? true : false;
}
public function Header() {
if ($this->header_xobjid === false) {
$this->header_xobjid = $this->startTemplate($this->w, $this->tMargin);
$headerfont = $this->getHeaderFont();
$headerdata = $this->getHeaderData();
$this->y = $this->header_margin;
if ($this->rtl) {
$this->x = $this->w - $this->original_rMargin;
} else {
$this->x = $this->original_lMargin;
}
if (($headerdata['logo']) AND ($headerdata['logo'] != K_BLANK_IMAGE)) {
$imgtype = TCPDF_IMAGES::getImageFileType(K_PATH_IMAGES.$headerdata['logo']);
if (($imgtype == 'eps') OR ($imgtype == 'ai')) {
$this->ImageEps(K_PATH_IMAGES.$headerdata['logo'], '', '', $headerdata['logo_width']);
} elseif ($imgtype == 'svg') {
$this->ImageSVG(K_PATH_IMAGES.$headerdata['logo'], '', '', $headerdata['logo_width']);
} else {
$this->Image(K_PATH_IMAGES.$headerdata['logo'], '', '', $headerdata['logo_width']);
}
$imgy = $this->getImageRBY();
} else {
$imgy = $this->y;
}
$cell_height = $this->getCellHeight($headerfont[2] / $this->k);
if ($this->getRTL()) {
$header_x = $this->original_rMargin + ($headerdata['logo_width'] * 1.1);
} else {
$header_x = $this->original_lMargin + ($headerdata['logo_width'] * 1.1);
}
$cw = $this->w - $this->original_lMargin - $this->original_rMargin - ($headerdata['logo_width'] * 1.1);
$this->SetTextColorArray($this->header_text_color);
$this->SetFont($headerfont[0], 'B', $headerfont[2] + 1);
$this->SetX($header_x);
$this->Cell($cw, $cell_height, $headerdata['title'], 0, 1, '', 0, '', 0);
$this->SetFont($headerfont[0], $headerfont[1], $headerfont[2]);
$this->SetX($header_x);
$this->MultiCell($cw, $cell_height, $headerdata['string'], 0, '', 0, 1, '', '', true, 0, false, true, 0, 'T', false);
$this->SetLineStyle(array('width' => 0.85 / $this->k, 'cap' => 'butt', 'join' => 'miter', 'dash' => 0, 'color' => $headerdata['line_color']));
$this->SetY((2.835 / $this->k) + max($imgy, $this->y));
if ($this->rtl) {
$this->SetX($this->original_rMargin);
} else {
$this->SetX($this->original_lMargin);
}
$this->Cell(($this->w - $this->original_lMargin - $this->original_rMargin), 0, '', 'T', 0, 'C');
$this->endTemplate();
}
$x = 0;
$dx = 0;
if (!$this->header_xobj_autoreset AND $this->booklet AND (($this->page % 2) == 0)) {
$dx = ($this->original_lMargin - $this->original_rMargin);
}
if ($this->rtl) {
$x = $this->w + $dx;
} else {
$x = 0 + $dx;
}
$this->printTemplate($this->header_xobjid, $x, 0, 0, 0, '', '', false);
if ($this->header_xobj_autoreset) {
$this->header_xobjid = false;
}
}
public function Footer() {
$cur_y = $this->y;
$this->SetTextColorArray($this->footer_text_color);
$line_width = (0.85 / $this->k);
$this->SetLineStyle(array('width' => $line_width, 'cap' => 'butt', 'join' => 'miter', 'dash' => 0, 'color' => $this->footer_line_color));
$barcode = $this->getBarcode();
if (!empty($barcode)) {
$this->Ln($line_width);
$barcode_width = round(($this->w - $this->original_lMargin - $this->original_rMargin) / 3);
$style = array(
'position' => $this->rtl?'R':'L',
'align' => $this->rtl?'R':'L',
'stretch' => false,
'fitwidth' => true,
'cellfitalign' => '',
'border' => false,
'padding' => 0,
'fgcolor' => array(0,0,0),
'bgcolor' => false,
'text' => false
);
$this->write1DBarcode($barcode, 'C128', '', $cur_y + $line_width, '', (($this->footer_margin / 3) - $line_width), 0.3, $style, '');
}
$w_page = isset($this->l['w_page']) ? $this->l['w_page'].' ' : '';
if (empty($this->pagegroups)) {
$pagenumtxt = $w_page.$this->getAliasNumPage().' / '.$this->getAliasNbPages();
} else {
$pagenumtxt = $w_page.$this->getPageNumGroupAlias().' / '.$this->getPageGroupAlias();
}
$this->SetY($cur_y);
if ($this->getRTL()) {
$this->SetX($this->original_rMargin);
$this->Cell(0, 0, $pagenumtxt, 'T', 0, 'L');
} else {
$this->SetX($this->original_lMargin);
$this->Cell(0, 0, $this->getAliasRightShift().$pagenumtxt, 'T', 0, 'R');
}
}
protected function setHeader() {
if (!$this->print_header OR ($this->state != 2)) {
return;
}
$this->InHeader = true;
$this->setGraphicVars($this->default_graphic_vars);
$temp_thead = $this->thead;
$temp_theadMargins = $this->theadMargins;
$lasth = $this->lasth;
$newline = $this->newline;
$this->_outSaveGraphicsState();
$this->rMargin = $this->original_rMargin;
$this->lMargin = $this->original_lMargin;
$this->SetCellPadding(0);
if ($this->rtl) {
$this->SetXY($this->original_rMargin, $this->header_margin);
} else {
$this->SetXY($this->original_lMargin, $this->header_margin);
}
$this->SetFont($this->header_font[0], $this->header_font[1], $this->header_font[2]);
$this->Header();
if ($this->rtl) {
$this->SetXY($this->original_rMargin, $this->tMargin);
} else {
$this->SetXY($this->original_lMargin, $this->tMargin);
}
$this->_outRestoreGraphicsState();
$this->lasth = $lasth;
$this->thead = $temp_thead;
$this->theadMargins = $temp_theadMargins;
$this->newline = $newline;
$this->InHeader = false;
}
protected function setFooter() {
if ($this->state != 2) {
return;
}
$this->InFooter = true;
$gvars = $this->getGraphicVars();
$this->footerpos[$this->page] = $this->pagelen[$this->page];
$this->_out("\n");
if ($this->print_footer) {
$this->setGraphicVars($this->default_graphic_vars);
$this->current_column = 0;
$this->num_columns = 1;
$temp_thead = $this->thead;
$temp_theadMargins = $this->theadMargins;
$lasth = $this->lasth;
$this->_outSaveGraphicsState();
$this->rMargin = $this->original_rMargin;
$this->lMargin = $this->original_lMargin;
$this->SetCellPadding(0);
$footer_y = $this->h - $this->footer_margin;
if ($this->rtl) {
$this->SetXY($this->original_rMargin, $footer_y);
} else {
$this->SetXY($this->original_lMargin, $footer_y);
}
$this->SetFont($this->footer_font[0], $this->footer_font[1], $this->footer_font[2]);
$this->Footer();
if ($this->rtl) {
$this->SetXY($this->original_rMargin, $this->tMargin);
} else {
$this->SetXY($this->original_lMargin, $this->tMargin);
}
$this->_outRestoreGraphicsState();
$this->lasth = $lasth;
$this->thead = $temp_thead;
$this->theadMargins = $temp_theadMargins;
}
$this->setGraphicVars($gvars);
$this->current_column = $gvars['current_column'];
$this->num_columns = $gvars['num_columns'];
$this->footerlen[$this->page] = $this->pagelen[$this->page] - $this->footerpos[$this->page] + 1;
$this->InFooter = false;
}
protected function inPageBody() {
return (($this->InHeader === false) AND ($this->InFooter === false));
}
protected function setTableHeader() {
if ($this->num_columns > 1) {
return;
}
if (isset($this->theadMargins['top'])) {
$this->tMargin = $this->theadMargins['top'];
$this->pagedim[$this->page]['tm'] = $this->tMargin;
$this->y = $this->tMargin;
}
if (!TCPDF_STATIC::empty_string($this->thead) AND (!$this->inthead)) {
$prev_lMargin = $this->lMargin;
$prev_rMargin = $this->rMargin;
$prev_cell_padding = $this->cell_padding;
$this->lMargin = $this->theadMargins['lmargin'] + ($this->pagedim[$this->page]['olm'] - $this->pagedim[$this->theadMargins['page']]['olm']);
$this->rMargin = $this->theadMargins['rmargin'] + ($this->pagedim[$this->page]['orm'] - $this->pagedim[$this->theadMargins['page']]['orm']);
$this->cell_padding = $this->theadMargins['cell_padding'];
if ($this->rtl) {
$this->x = $this->w - $this->rMargin;
} else {
$this->x = $this->lMargin;
}
if ($this->theadMargins['cell']) {
if ($this->rtl) {
$this->x -= $this->cell_padding['R'];
} else {
$this->x += $this->cell_padding['L'];
}
}
$gvars = $this->getGraphicVars();
if (!empty($this->theadMargins['gvars'])) {
$this->setGraphicVars($this->theadMargins['gvars']);
$this->rMargin = $gvars['rMargin'];
$this->lMargin = $gvars['lMargin'];
}
$this->writeHTML($this->thead, false, false, false, false, '');
$this->setGraphicVars($gvars);
if (!isset($this->theadMargins['top'])) {
$this->theadMargins['top'] = $this->tMargin;
}
if (!isset($this->columns[0]['th'])) {
$this->columns[0]['th'] = array();
}
$this->columns[0]['th']['\''.$this->page.'\''] = $this->y;
$this->tMargin = $this->y;
$this->pagedim[$this->page]['tm'] = $this->tMargin;
$this->lasth = 0;
$this->lMargin = $prev_lMargin;
$this->rMargin = $prev_rMargin;
$this->cell_padding = $prev_cell_padding;
}
}
public function PageNo() {
return $this->page;
}
public function getAllSpotColors() {
return $this->spot_colors;
}
public function AddSpotColor($name, $c, $m, $y, $k) {
if (!isset($this->spot_colors[$name])) {
$i = (1 + count($this->spot_colors));
$this->spot_colors[$name] = array('C' => $c, 'M' => $m, 'Y' => $y, 'K' => $k, 'name' => $name, 'i' => $i);
}
}
public function setSpotColor($type, $name, $tint=100) {
$spotcolor = TCPDF_COLORS::getSpotColor($name, $this->spot_colors);
if ($spotcolor === false) {
$this->Error('Undefined spot color: '.$name.', you must add it using the AddSpotColor() method.');
}
$tint = (max(0, min(100, $tint)) / 100);
$pdfcolor = sprintf('/CS%d ', $this->spot_colors[$name]['i']);
switch ($type) {
case 'draw': {
$pdfcolor .= sprintf('CS %F SCN', $tint);
$this->DrawColor = $pdfcolor;
$this->strokecolor = $spotcolor;
break;
}
case 'fill': {
$pdfcolor .= sprintf('cs %F scn', $tint);
$this->FillColor = $pdfcolor;
$this->bgcolor = $spotcolor;
break;
}
case 'text': {
$pdfcolor .= sprintf('cs %F scn', $tint);
$this->TextColor = $pdfcolor;
$this->fgcolor = $spotcolor;
break;
}
}
$this->ColorFlag = ($this->FillColor != $this->TextColor);
if ($this->state == 2) {
$this->_out($pdfcolor);
}
if ($this->inxobj) {
$this->xobjects[$this->xobjid]['spot_colors'][$name] = $this->spot_colors[$name];
}
return $pdfcolor;
}
public function SetDrawSpotColor($name, $tint=100) {
$this->setSpotColor('draw', $name, $tint);
}
public function SetFillSpotColor($name, $tint=100) {
$this->setSpotColor('fill', $name, $tint);
}
public function SetTextSpotColor($name, $tint=100) {
$this->setSpotColor('text', $name, $tint);
}
public function setColorArray($type, $color, $ret=false) {
if (is_array($color)) {
$color = array_values($color);
$c = isset($color[0]) ? $color[0] : -1;
$m = isset($color[1]) ? $color[1] : -1;
$y = isset($color[2]) ? $color[2] : -1;
$k = isset($color[3]) ? $color[3] : -1;
$name = isset($color[4]) ? $color[4] : '';
if ($c >= 0) {
return $this->setColor($type, $c, $m, $y, $k, $ret, $name);
}
}
return '';
}
public function SetDrawColorArray($color, $ret=false) {
return $this->setColorArray('draw', $color, $ret);
}
public function SetFillColorArray($color, $ret=false) {
return $this->setColorArray('fill', $color, $ret);
}
public function SetTextColorArray($color, $ret=false) {
return $this->setColorArray('text', $color, $ret);
}
public function setColor($type, $col1=0, $col2=-1, $col3=-1, $col4=-1, $ret=false, $name='') {
if (!is_numeric($col1)) {
$col1 = 0;
}
if (!is_numeric($col2)) {
$col2 = -1;
}
if (!is_numeric($col3)) {
$col3 = -1;
}
if (!is_numeric($col4)) {
$col4 = -1;
}
$suffix = '';
if (($col2 == -1) AND ($col3 == -1) AND ($col4 == -1)) {
$col1 = max(0, min(255, $col1));
$intcolor = array('G' => $col1);
$pdfcolor = sprintf('%F ', ($col1 / 255));
$suffix = 'g';
} elseif ($col4 == -1) {
$col1 = max(0, min(255, $col1));
$col2 = max(0, min(255, $col2));
$col3 = max(0, min(255, $col3));
$intcolor = array('R' => $col1, 'G' => $col2, 'B' => $col3);
$pdfcolor = sprintf('%F %F %F ', ($col1 / 255), ($col2 / 255), ($col3 / 255));
$suffix = 'rg';
} else {
$col1 = max(0, min(100, $col1));
$col2 = max(0, min(100, $col2));
$col3 = max(0, min(100, $col3));
$col4 = max(0, min(100, $col4));
if (empty($name)) {
$intcolor = array('C' => $col1, 'M' => $col2, 'Y' => $col3, 'K' => $col4);
$pdfcolor = sprintf('%F %F %F %F ', ($col1 / 100), ($col2 / 100), ($col3 / 100), ($col4 / 100));
$suffix = 'k';
} else {
$intcolor = array('C' => $col1, 'M' => $col2, 'Y' => $col3, 'K' => $col4, 'name' => $name);
$this->AddSpotColor($name, $col1, $col2, $col3, $col4);
$pdfcolor = $this->setSpotColor($type, $name, 100);
}
}
switch ($type) {
case 'draw': {
$pdfcolor .= strtoupper($suffix);
$this->DrawColor = $pdfcolor;
$this->strokecolor = $intcolor;
break;
}
case 'fill': {
$pdfcolor .= $suffix;
$this->FillColor = $pdfcolor;
$this->bgcolor = $intcolor;
break;
}
case 'text': {
$pdfcolor .= $suffix;
$this->TextColor = $pdfcolor;
$this->fgcolor = $intcolor;
break;
}
}
$this->ColorFlag = ($this->FillColor != $this->TextColor);
if (($type != 'text') AND ($this->state == 2)) {
if (!$ret) {
$this->_out($pdfcolor);
}
return $pdfcolor;
}
return '';
}
public function SetDrawColor($col1=0, $col2=-1, $col3=-1, $col4=-1, $ret=false, $name='') {
return $this->setColor('draw', $col1, $col2, $col3, $col4, $ret, $name);
}
public function SetFillColor($col1=0, $col2=-1, $col3=-1, $col4=-1, $ret=false, $name='') {
return $this->setColor('fill', $col1, $col2, $col3, $col4, $ret, $name);
}
public function SetTextColor($col1=0, $col2=-1, $col3=-1, $col4=-1, $ret=false, $name='') {
return $this->setColor('text', $col1, $col2, $col3, $col4, $ret, $name);
}
public function GetStringWidth($s, $fontname='', $fontstyle='', $fontsize=0, $getarray=false) {
return $this->GetArrStringWidth(TCPDF_FONTS::utf8Bidi(TCPDF_FONTS::UTF8StringToArray($s, $this->isunicode, $this->CurrentFont), $s, $this->tmprtl, $this->isunicode, $this->CurrentFont), $fontname, $fontstyle, $fontsize, $getarray);
}
public function GetArrStringWidth($sa, $fontname='', $fontstyle='', $fontsize=0, $getarray=false) {
if (!TCPDF_STATIC::empty_string($fontname)) {
$prev_FontFamily = $this->FontFamily;
$prev_FontStyle = $this->FontStyle;
$prev_FontSizePt = $this->FontSizePt;
$this->SetFont($fontname, $fontstyle, $fontsize, '', 'default', false);
}
if ($this->isunicode AND (!$this->isUnicodeFont())) {
$sa = TCPDF_FONTS::UTF8ArrToLatin1Arr($sa);
}
$w = 0;
$wa = array();
foreach ($sa as $ck => $char) {
$cw = $this->GetCharWidth($char, isset($sa[($ck + 1)]));
$wa[] = $cw;
$w += $cw;
}
if (!TCPDF_STATIC::empty_string($fontname)) {
$this->SetFont($prev_FontFamily, $prev_FontStyle, $prev_FontSizePt, '', 'default', false);
}
if ($getarray) {
return $wa;
}
return $w;
}
public function GetCharWidth($char, $notlast=true) {
$chw = $this->getRawCharWidth($char);
if (($this->font_spacing < 0) OR (($this->font_spacing > 0) AND $notlast)) {
$chw += $this->font_spacing;
}
if ($this->font_stretching != 100) {
$chw *= ($this->font_stretching / 100);
}
return $chw;
}
public function getRawCharWidth($char) {
if ($char == 173) {
return (0);
}
if (isset($this->CurrentFont['cw'][$char])) {
$w = $this->CurrentFont['cw'][$char];
} elseif (isset($this->CurrentFont['dw'])) {
$w = $this->CurrentFont['dw'];
} elseif (isset($this->CurrentFont['cw'][32])) {
$w = $this->CurrentFont['cw'][32];
} else {
$w = 600;
}
return $this->getAbsFontMeasure($w);
}
public function GetNumChars($s) {
if ($this->isUnicodeFont()) {
return count(TCPDF_FONTS::UTF8StringToArray($s, $this->isunicode, $this->CurrentFont));
}
return strlen($s);
}
protected function getFontsList() {
if (($fontsdir = opendir(TCPDF_FONTS::_getfontpath())) !== false) {
while (($file = readdir($fontsdir)) !== false) {
if (substr($file, -4) == '.php') {
array_push($this->fontlist, strtolower(basename($file, '.php')));
}
}
closedir($fontsdir);
}
}
public function AddFont($family, $style='', $fontfile='', $subset='default') {
if ($subset === 'default') {
$subset = $this->font_subsetting;
}
if ($this->pdfa_mode) {
$subset = false;
}
if (TCPDF_STATIC::empty_string($family)) {
if (!TCPDF_STATIC::empty_string($this->FontFamily)) {
$family = $this->FontFamily;
} else {
$this->Error('Empty font family');
}
}
if (substr($family, -1) == 'I') {
$style .= 'I';
$family = substr($family, 0, -1);
}
if (substr($family, -1) == 'B') {
$style .= 'B';
$family = substr($family, 0, -1);
}
$family = strtolower($family);
if ((!$this->isunicode) AND ($family == 'arial')) {
$family = 'helvetica';
}
if (($family == 'symbol') OR ($family == 'zapfdingbats')) {
$style = '';
}
if ($this->pdfa_mode AND (isset($this->CoreFonts[$family]))) {
$family = 'pdfa'.$family;
}
$tempstyle = strtoupper($style);
$style = '';
if (strpos($tempstyle, 'U') !== false) {
$this->underline = true;
} else {
$this->underline = false;
}
if (strpos($tempstyle, 'D') !== false) {
$this->linethrough = true;
} else {
$this->linethrough = false;
}
if (strpos($tempstyle, 'O') !== false) {
$this->overline = true;
} else {
$this->overline = false;
}
if (strpos($tempstyle, 'B') !== false) {
$style .= 'B';
}
if (strpos($tempstyle, 'I') !== false) {
$style .= 'I';
}
$bistyle = $style;
$fontkey = $family.$style;
$font_style = $style.($this->underline ? 'U' : '').($this->linethrough ? 'D' : '').($this->overline ? 'O' : '');
$fontdata = array('fontkey' => $fontkey, 'family' => $family, 'style' => $font_style);
$fb = $this->getFontBuffer($fontkey);
if ($fb !== false) {
if ($this->inxobj) {
$this->xobjects[$this->xobjid]['fonts'][$fontkey] = $fb['i'];
}
return $fontdata;
}
$fontdir = false;
if (!TCPDF_STATIC::empty_string($fontfile)) {
$fontdir = dirname($fontfile);
if (TCPDF_STATIC::empty_string($fontdir) OR ($fontdir == '.')) {
$fontdir = '';
} else {
$fontdir .= '/';
}
}
$missing_style = false;
if (TCPDF_STATIC::empty_string($fontfile) OR (!@file_exists($fontfile))) {
$tmp_fontfile = str_replace(' ', '', $family).strtolower($style).'.php';
$fontfile = TCPDF_FONTS::getFontFullPath($tmp_fontfile, $fontdir);
if (TCPDF_STATIC::empty_string($fontfile)) {
$missing_style = true;
$tmp_fontfile = str_replace(' ', '', $family).'.php';
$fontfile = TCPDF_FONTS::getFontFullPath($tmp_fontfile, $fontdir);
}
}
if (!TCPDF_STATIC::empty_string($fontfile) AND (@file_exists($fontfile))) {
include($fontfile);
} else {
$this->Error('Could not include font definition file: '.$family.'');
}
if ((!isset($type)) OR (!isset($cw))) {
$this->Error('The font definition file has a bad format: '.$fontfile.'');
}
if (!isset($file) OR TCPDF_STATIC::empty_string($file)) {
$file = '';
}
if (!isset($enc) OR TCPDF_STATIC::empty_string($enc)) {
$enc = '';
}
if (!isset($cidinfo) OR TCPDF_STATIC::empty_string($cidinfo)) {
$cidinfo = array('Registry'=>'Adobe', 'Ordering'=>'Identity', 'Supplement'=>0);
$cidinfo['uni2cid'] = array();
}
if (!isset($ctg) OR TCPDF_STATIC::empty_string($ctg)) {
$ctg = '';
}
if (!isset($desc) OR TCPDF_STATIC::empty_string($desc)) {
$desc = array();
}
if (!isset($up) OR TCPDF_STATIC::empty_string($up)) {
$up = -100;
}
if (!isset($ut) OR TCPDF_STATIC::empty_string($ut)) {
$ut = 50;
}
if (!isset($cw) OR TCPDF_STATIC::empty_string($cw)) {
$cw = array();
}
if (!isset($dw) OR TCPDF_STATIC::empty_string($dw)) {
if (isset($desc['MissingWidth']) AND ($desc['MissingWidth'] > 0)) {
$dw = $desc['MissingWidth'];
} elseif (isset($cw[32])) {
$dw = $cw[32];
} else {
$dw = 600;
}
}
++$this->numfonts;
if ($type == 'core') {
$name = $this->CoreFonts[$fontkey];
$subset = false;
} elseif (($type == 'TrueType') OR ($type == 'Type1')) {
$subset = false;
} elseif ($type == 'TrueTypeUnicode') {
$enc = 'Identity-H';
} elseif ($type == 'cidfont0') {
if ($this->pdfa_mode) {
$this->Error('All fonts must be embedded in PDF/A mode!');
}
} else {
$this->Error('Unknow font type: '.$type.'');
}
if (!isset($name) OR empty($name)) {
$name = $fontkey;
}
if (($type != 'core') AND $missing_style) {
$styles = array('' => '', 'B' => ',Bold', 'I' => ',Italic', 'BI' => ',BoldItalic');
$name .= $styles[$bistyle];
if (strpos($bistyle, 'B') !== false) {
if (isset($desc['StemV'])) {
$desc['StemV'] = round($desc['StemV'] * 1.75);
} else {
$desc['StemV'] = 123;
}
}
if (strpos($bistyle, 'I') !== false) {
if (isset($desc['ItalicAngle'])) {
$desc['ItalicAngle'] -= 11;
} else {
$desc['ItalicAngle'] = -11;
}
if (isset($desc['Flags'])) {
$desc['Flags'] |= 64;
} else {
$desc['Flags'] = 64;
}
}
}
if (!isset($cbbox)) {
$cbbox = array();
}
$subsetchars = array_fill(0, 255, true);
$this->setFontBuffer($fontkey, array('fontkey' => $fontkey, 'i' => $this->numfonts, 'type' => $type, 'name' => $name, 'desc' => $desc, 'up' => $up, 'ut' => $ut, 'cw' => $cw, 'cbbox' => $cbbox, 'dw' => $dw, 'enc' => $enc, 'cidinfo' => $cidinfo, 'file' => $file, 'ctg' => $ctg, 'subset' => $subset, 'subsetchars' => $subsetchars));
if ($this->inxobj) {
$this->xobjects[$this->xobjid]['fonts'][$fontkey] = $this->numfonts;
}
if (isset($diff) AND (!empty($diff))) {
$d = 0;
$nb = count($this->diffs);
for ($i=1; $i <= $nb; ++$i) {
if ($this->diffs[$i] == $diff) {
$d = $i;
break;
}
}
if ($d == 0) {
$d = $nb + 1;
$this->diffs[$d] = $diff;
}
$this->setFontSubBuffer($fontkey, 'diff', $d);
}
if (!TCPDF_STATIC::empty_string($file)) {
if (!isset($this->FontFiles[$file])) {
if ((strcasecmp($type,'TrueType') == 0) OR (strcasecmp($type, 'TrueTypeUnicode') == 0)) {
$this->FontFiles[$file] = array('length1' => $originalsize, 'fontdir' => $fontdir, 'subset' => $subset, 'fontkeys' => array($fontkey));
} elseif ($type != 'core') {
$this->FontFiles[$file] = array('length1' => $size1, 'length2' => $size2, 'fontdir' => $fontdir, 'subset' => $subset, 'fontkeys' => array($fontkey));
}
} else {
$this->FontFiles[$file]['subset'] = ($this->FontFiles[$file]['subset'] AND $subset);
if (!in_array($fontkey, $this->FontFiles[$file]['fontkeys'])) {
$this->FontFiles[$file]['fontkeys'][] = $fontkey;
}
}
}
return $fontdata;
}
public function SetFont($family, $style='', $size=null, $fontfile='', $subset='default', $out=true) {
if ($size === null) {
$size = $this->FontSizePt;
}
if ($size < 0) {
$size = 0;
}
$fontdata = $this->AddFont($family, $style, $fontfile, $subset);
$this->FontFamily = $fontdata['family'];
$this->FontStyle = $fontdata['style'];
if (isset($this->CurrentFont['fontkey']) AND isset($this->CurrentFont['subsetchars'])) {
$this->setFontSubBuffer($this->CurrentFont['fontkey'], 'subsetchars', $this->CurrentFont['subsetchars']);
}
$this->CurrentFont = $this->getFontBuffer($fontdata['fontkey']);
$this->SetFontSize($size, $out);
}
public function SetFontSize($size, $out=true) {
$this->FontSizePt = $size;
$this->FontSize = $size / $this->k;
if (isset($this->CurrentFont['desc']['FontBBox'])) {
$bbox = explode(' ', substr($this->CurrentFont['desc']['FontBBox'], 1, -1));
$font_height = ((intval($bbox[3]) - intval($bbox[1])) * $size / 1000);
} else {
$font_height = $size * 1.219;
}
if (isset($this->CurrentFont['desc']['Ascent']) AND ($this->CurrentFont['desc']['Ascent'] > 0)) {
$font_ascent = ($this->CurrentFont['desc']['Ascent'] * $size / 1000);
}
if (isset($this->CurrentFont['desc']['Descent']) AND ($this->CurrentFont['desc']['Descent'] <= 0)) {
$font_descent = (- $this->CurrentFont['desc']['Descent'] * $size / 1000);
}
if (!isset($font_ascent) AND !isset($font_descent)) {
$font_ascent = 0.76 * $font_height;
$font_descent = $font_height - $font_ascent;
} elseif (!isset($font_descent)) {
$font_descent = $font_height - $font_ascent;
} elseif (!isset($font_ascent)) {
$font_ascent = $font_height - $font_descent;
}
$this->FontAscent = ($font_ascent / $this->k);
$this->FontDescent = ($font_descent / $this->k);
if ($out AND ($this->page > 0) AND (isset($this->CurrentFont['i'])) AND ($this->state == 2)) {
$this->_out(sprintf('BT /F%d %F Tf ET', $this->CurrentFont['i'], $this->FontSizePt));
}
}
public function getFontBBox() {
$fbbox = array();
if (isset($this->CurrentFont['desc']['FontBBox'])) {
$tmpbbox = explode(' ', substr($this->CurrentFont['desc']['FontBBox'], 1, -1));
$fbbox = array_map(array($this,'getAbsFontMeasure'), $tmpbbox);
} else {
if (isset($this->CurrentFont['desc']['MaxWidth'])) {
$maxw = $this->getAbsFontMeasure(intval($this->CurrentFont['desc']['MaxWidth']));
} else {
$maxw = 0;
if (isset($this->CurrentFont['desc']['MissingWidth'])) {
$maxw = max($maxw, $this->CurrentFont['desc']['MissingWidth']);
}
if (isset($this->CurrentFont['desc']['AvgWidth'])) {
$maxw = max($maxw, $this->CurrentFont['desc']['AvgWidth']);
}
if (isset($this->CurrentFont['dw'])) {
$maxw = max($maxw, $this->CurrentFont['dw']);
}
foreach ($this->CurrentFont['cw'] as $char => $w) {
$maxw = max($maxw, $w);
}
if ($maxw == 0) {
$maxw = 600;
}
$maxw = $this->getAbsFontMeasure($maxw);
}
$fbbox = array(0, (0 - $this->FontDescent), $maxw, $this->FontAscent);
}
return $fbbox;
}
public function getAbsFontMeasure($s) {
return ($s * $this->FontSize / 1000);
}
public function getCharBBox($char) {
$c = intval($char);
if (isset($this->CurrentFont['cw'][$c])) {
$result = array(0,0,0,0);
if (isset($this->CurrentFont['cbbox'][$c])) {
$result = $this->CurrentFont['cbbox'][$c];
}
return array_map(array($this,'getAbsFontMeasure'), $result);
}
return false;
}
public function getFontDescent($font, $style='', $size=0) {
$fontdata = $this->AddFont($font, $style);
$fontinfo = $this->getFontBuffer($fontdata['fontkey']);
if (isset($fontinfo['desc']['Descent']) AND ($fontinfo['desc']['Descent'] <= 0)) {
$descent = (- $fontinfo['desc']['Descent'] * $size / 1000);
} else {
$descent = (1.219 * 0.24 * $size);
}
return ($descent / $this->k);
}
public function getFontAscent($font, $style='', $size=0) {
$fontdata = $this->AddFont($font, $style);
$fontinfo = $this->getFontBuffer($fontdata['fontkey']);
if (isset($fontinfo['desc']['Ascent']) AND ($fontinfo['desc']['Ascent'] > 0)) {
$ascent = ($fontinfo['desc']['Ascent'] * $size / 1000);
} else {
$ascent = 1.219 * 0.76 * $size;
}
return ($ascent / $this->k);
}
public function isCharDefined($char, $font='', $style='') {
if (is_string($char)) {
$char = TCPDF_FONTS::UTF8StringToArray($char, $this->isunicode, $this->CurrentFont);
$char = $char[0];
}
if (TCPDF_STATIC::empty_string($font)) {
if (TCPDF_STATIC::empty_string($style)) {
return (isset($this->CurrentFont['cw'][intval($char)]));
}
$font = $this->FontFamily;
}
$fontdata = $this->AddFont($font, $style);
$fontinfo = $this->getFontBuffer($fontdata['fontkey']);
return (isset($fontinfo['cw'][intval($char)]));
}
public function replaceMissingChars($text, $font='', $style='', $subs=array()) {
if (empty($subs)) {
return $text;
}
if (TCPDF_STATIC::empty_string($font)) {
$font = $this->FontFamily;
}
$fontdata = $this->AddFont($font, $style);
$fontinfo = $this->getFontBuffer($fontdata['fontkey']);
$uniarr = TCPDF_FONTS::UTF8StringToArray($text, $this->isunicode, $this->CurrentFont);
foreach ($uniarr as $k => $chr) {
if (!isset($fontinfo['cw'][$chr])) {
if (isset($subs[$chr])) {
if (is_array($subs[$chr])) {
foreach($subs[$chr] as $s) {
if (isset($fontinfo['cw'][$s])) {
$uniarr[$k] = $s;
break;
}
}
} elseif (isset($fontinfo['cw'][$subs[$chr]])) {
$uniarr[$k] = $subs[$chr];
}
}
}
}
return TCPDF_FONTS::UniArrSubString(TCPDF_FONTS::UTF8ArrayToUniArray($uniarr, $this->isunicode));
}
public function SetDefaultMonospacedFont($font) {
$this->default_monospaced_font = $font;
}
public function AddLink() {
$n = count($this->links) + 1;
$this->links[$n] = array('p' => 0, 'y' => 0, 'f' => false);
return $n;
}
public function SetLink($link, $y=0, $page=-1) {
$fixed = false;
if (!empty($page) AND ($page[0] == '*')) {
$page = intval(substr($page, 1));
$fixed = true;
}
if ($page < 0) {
$page = $this->page;
}
if ($y == -1) {
$y = $this->y;
}
$this->links[$link] = array('p' => $page, 'y' => $y, 'f' => $fixed);
}
public function Link($x, $y, $w, $h, $link, $spaces=0) {
$this->Annotation($x, $y, $w, $h, $link, array('Subtype'=>'Link'), $spaces);
}
public function Annotation($x, $y, $w, $h, $text, $opt=array('Subtype'=>'Text'), $spaces=0) {
if ($this->inxobj) {
$this->xobjects[$this->xobjid]['annotations'][] = array('x' => $x, 'y' => $y, 'w' => $w, 'h' => $h, 'text' => $text, 'opt' => $opt, 'spaces' => $spaces);
return;
}
if ($x === '') {
$x = $this->x;
}
if ($y === '') {
$y = $this->y;
}
list($x, $y) = $this->checkPageRegions($h, $x, $y);
if (isset($this->transfmatrix) AND !empty($this->transfmatrix)) {
for ($i=$this->transfmatrix_key; $i > 0; --$i) {
$maxid = count($this->transfmatrix[$i]) - 1;
for ($j=$maxid; $j >= 0; --$j) {
$ctm = $this->transfmatrix[$i][$j];
if (isset($ctm['a'])) {
$x = $x * $this->k;
$y = ($this->h - $y) * $this->k;
$w = $w * $this->k;
$h = $h * $this->k;
$xt = $x;
$yt = $y;
$x1 = ($ctm['a'] * $xt) + ($ctm['c'] * $yt) + $ctm['e'];
$y1 = ($ctm['b'] * $xt) + ($ctm['d'] * $yt) + $ctm['f'];
$xt = $x + $w;
$yt = $y;
$x2 = ($ctm['a'] * $xt) + ($ctm['c'] * $yt) + $ctm['e'];
$y2 = ($ctm['b'] * $xt) + ($ctm['d'] * $yt) + $ctm['f'];
$xt = $x;
$yt = $y - $h;
$x3 = ($ctm['a'] * $xt) + ($ctm['c'] * $yt) + $ctm['e'];
$y3 = ($ctm['b'] * $xt) + ($ctm['d'] * $yt) + $ctm['f'];
$xt = $x + $w;
$yt = $y - $h;
$x4 = ($ctm['a'] * $xt) + ($ctm['c'] * $yt) + $ctm['e'];
$y4 = ($ctm['b'] * $xt) + ($ctm['d'] * $yt) + $ctm['f'];
$x = min($x1, $x2, $x3, $x4);
$y = max($y1, $y2, $y3, $y4);
$w = (max($x1, $x2, $x3, $x4) - $x) / $this->k;
$h = ($y - min($y1, $y2, $y3, $y4)) / $this->k;
$x = $x / $this->k;
$y = $this->h - ($y / $this->k);
}
}
}
}
if ($this->page <= 0) {
$page = 1;
} else {
$page = $this->page;
}
if (!isset($this->PageAnnots[$page])) {
$this->PageAnnots[$page] = array();
}
$this->PageAnnots[$page][] = array('n' => ++$this->n, 'x' => $x, 'y' => $y, 'w' => $w, 'h' => $h, 'txt' => $text, 'opt' => $opt, 'numspaces' => $spaces);
if (!$this->pdfa_mode) {
if ((($opt['Subtype'] == 'FileAttachment') OR ($opt['Subtype'] == 'Sound')) AND (!TCPDF_STATIC::empty_string($opt['FS']))
AND (@file_exists($opt['FS']) OR TCPDF_STATIC::isValidURL($opt['FS']))
AND (!isset($this->embeddedfiles[basename($opt['FS'])]))) {
$this->embeddedfiles[basename($opt['FS'])] = array('f' => ++$this->n, 'n' => ++$this->n, 'file' => $opt['FS']);
}
}
if (isset($opt['mk']['i']) AND @file_exists($opt['mk']['i'])) {
$this->Image($opt['mk']['i'], '', '', 10, 10, '', '', '', false, 300, '', false, false, 0, false, true);
}
if (isset($opt['mk']['ri']) AND @file_exists($opt['mk']['ri'])) {
$this->Image($opt['mk']['ri'], '', '', 0, 0, '', '', '', false, 300, '', false, false, 0, false, true);
}
if (isset($opt['mk']['ix']) AND @file_exists($opt['mk']['ix'])) {
$this->Image($opt['mk']['ix'], '', '', 0, 0, '', '', '', false, 300, '', false, false, 0, false, true);
}
}
protected function _putEmbeddedFiles() {
if ($this->pdfa_mode) {
return;
}
reset($this->embeddedfiles);
foreach ($this->embeddedfiles as $filename => $filedata) {
$data = TCPDF_STATIC::fileGetContents($filedata['file']);
if ($data !== FALSE) {
$rawsize = strlen($data);
if ($rawsize > 0) {
$this->efnames[$filename] = $filedata['f'].' 0 R';
$out = $this->_getobj($filedata['f'])."\n";
$out .= '<</Type /Filespec /F '.$this->_datastring($filename, $filedata['f']).' /EF <</F '.$filedata['n'].' 0 R>> >>';
$out .= "\n".'endobj';
$this->_out($out);
$filter = '';
if ($this->compress) {
$data = gzcompress($data);
$filter = ' /Filter /FlateDecode';
}
$stream = $this->_getrawstream($data, $filedata['n']);
$out = $this->_getobj($filedata['n'])."\n";
$out .= '<< /Type /EmbeddedFile'.$filter.' /Length '.strlen($stream).' /Params <</Size '.$rawsize.'>> >>';
$out .= ' stream'."\n".$stream."\n".'endstream';
$out .= "\n".'endobj';
$this->_out($out);
}
}
}
}
public function Text($x, $y, $txt, $fstroke=false, $fclip=false, $ffill=true, $border=0, $ln=0, $align='', $fill=false, $link='', $stretch=0, $ignore_min_height=false, $calign='T', $valign='M', $rtloff=false) {
$textrendermode = $this->textrendermode;
$textstrokewidth = $this->textstrokewidth;
$this->setTextRenderingMode($fstroke, $ffill, $fclip);
$this->SetXY($x, $y, $rtloff);
$this->Cell(0, 0, $txt, $border, $ln, $align, $fill, $link, $stretch, $ignore_min_height, $calign, $valign);
$this->textrendermode = $textrendermode;
$this->textstrokewidth = $textstrokewidth;
}
public function AcceptPageBreak() {
if ($this->num_columns > 1) {
if ($this->current_column < ($this->num_columns - 1)) {
$this->selectColumn($this->current_column + 1);
} elseif ($this->AutoPageBreak) {
$this->AddPage();
$this->selectColumn(0);
}
return false;
}
return $this->AutoPageBreak;
}
protected function checkPageBreak($h=0, $y='', $addpage=true) {
if (TCPDF_STATIC::empty_string($y)) {
$y = $this->y;
}
$current_page = $this->page;
if ((($y + $h) > $this->PageBreakTrigger) AND ($this->inPageBody()) AND ($this->AcceptPageBreak())) {
if ($addpage) {
$x = $this->x;
$this->AddPage($this->CurOrientation);
$this->y = $this->tMargin;
$oldpage = $this->page - 1;
if ($this->rtl) {
if ($this->pagedim[$this->page]['orm'] != $this->pagedim[$oldpage]['orm']) {
$this->x = $x - ($this->pagedim[$this->page]['orm'] - $this->pagedim[$oldpage]['orm']);
} else {
$this->x = $x;
}
} else {
if ($this->pagedim[$this->page]['olm'] != $this->pagedim[$oldpage]['olm']) {
$this->x = $x + ($this->pagedim[$this->page]['olm'] - $this->pagedim[$oldpage]['olm']);
} else {
$this->x = $x;
}
}
}
return true;
}
if ($current_page != $this->page) {
return true;
}
return false;
}
public function Cell($w, $h=0, $txt='', $border=0, $ln=0, $align='', $fill=false, $link='', $stretch=0, $ignore_min_height=false, $calign='T', $valign='M') {
$prev_cell_margin = $this->cell_margin;
$prev_cell_padding = $this->cell_padding;
$this->adjustCellPadding($border);
if (!$ignore_min_height) {
$min_cell_height = $this->getCellHeight($this->FontSize);
if ($h < $min_cell_height) {
$h = $min_cell_height;
}
}
$this->checkPageBreak($h + $this->cell_margin['T'] + $this->cell_margin['B']);
if ($this->txtshadow['enabled']) {
$x = $this->x;
$y = $this->y;
$bc = $this->bgcolor;
$fc = $this->fgcolor;
$sc = $this->strokecolor;
$alpha = $this->alpha;
$this->x += $this->txtshadow['depth_w'];
$this->y += $this->txtshadow['depth_h'];
$this->SetFillColorArray($this->txtshadow['color']);
$this->SetTextColorArray($this->txtshadow['color']);
$this->SetDrawColorArray($this->txtshadow['color']);
if ($this->txtshadow['opacity'] != $alpha['CA']) {
$this->setAlpha($this->txtshadow['opacity'], $this->txtshadow['blend_mode']);
}
if ($this->state == 2) {
$this->_out($this->getCellCode($w, $h, $txt, $border, $ln, $align, $fill, $link, $stretch, true, $calign, $valign));
}
$this->x = $x;
$this->y = $y;
$this->SetFillColorArray($bc);
$this->SetTextColorArray($fc);
$this->SetDrawColorArray($sc);
if ($this->txtshadow['opacity'] != $alpha['CA']) {
$this->setAlpha($alpha['CA'], $alpha['BM'], $alpha['ca'], $alpha['AIS']);
}
}
if ($this->state == 2) {
$this->_out($this->getCellCode($w, $h, $txt, $border, $ln, $align, $fill, $link, $stretch, true, $calign, $valign));
}
$this->cell_padding = $prev_cell_padding;
$this->cell_margin = $prev_cell_margin;
}
protected function getCellCode($w, $h=0, $txt='', $border=0, $ln=0, $align='', $fill=false, $link='', $stretch=0, $ignore_min_height=false, $calign='T', $valign='M') {
$txt = str_replace(TCPDF_FONTS::unichr(160, $this->isunicode), ' ', $txt);
$prev_cell_margin = $this->cell_margin;
$prev_cell_padding = $this->cell_padding;
$txt = TCPDF_STATIC::removeSHY($txt, $this->isunicode);
$rs = '';
$this->adjustCellPadding($border);
if (!$ignore_min_height) {
$min_cell_height = $this->getCellHeight($this->FontSize);
if ($h < $min_cell_height) {
$h = $min_cell_height;
}
}
$k = $this->k;
list($this->x, $this->y) = $this->checkPageRegions($h, $this->x, $this->y);
if ($this->rtl) {
$x = $this->x - $this->cell_margin['R'];
} else {
$x = $this->x + $this->cell_margin['L'];
}
$y = $this->y + $this->cell_margin['T'];
$prev_font_stretching = $this->font_stretching;
$prev_font_spacing = $this->font_spacing;
switch ($calign) {
case 'A': {
switch ($valign) {
case 'T': {
$y -= $this->cell_padding['T'];
break;
}
case 'B': {
$y -= ($h - $this->cell_padding['B'] - $this->FontAscent - $this->FontDescent);
break;
}
default:
case 'C':
case 'M': {
$y -= (($h - $this->FontAscent - $this->FontDescent) / 2);
break;
}
}
break;
}
case 'L': {
switch ($valign) {
case 'T': {
$y -= ($this->cell_padding['T'] + $this->FontAscent);
break;
}
case 'B': {
$y -= ($h - $this->cell_padding['B'] - $this->FontDescent);
break;
}
default:
case 'C':
case 'M': {
$y -= (($h + $this->FontAscent - $this->FontDescent) / 2);
break;
}
}
break;
}
case 'D': {
switch ($valign) {
case 'T': {
$y -= ($this->cell_padding['T'] + $this->FontAscent + $this->FontDescent);
break;
}
case 'B': {
$y -= ($h - $this->cell_padding['B']);
break;
}
default:
case 'C':
case 'M': {
$y -= (($h + $this->FontAscent + $this->FontDescent) / 2);
break;
}
}
break;
}
case 'B': {
$y -= $h;
break;
}
case 'C':
case 'M': {
$y -= ($h / 2);
break;
}
default:
case 'T': {
break;
}
}
switch ($valign) {
case 'T': {
$yt = $y + $this->cell_padding['T'];
break;
}
case 'B': {
$yt = $y + $h - $this->cell_padding['B'] - $this->FontAscent - $this->FontDescent;
break;
}
default:
case 'C':
case 'M': {
$yt = $y + (($h - $this->FontAscent - $this->FontDescent) / 2);
break;
}
}
$basefonty = $yt + $this->FontAscent;
if (TCPDF_STATIC::empty_string($w) OR ($w <= 0)) {
if ($this->rtl) {
$w = $x - $this->lMargin;
} else {
$w = $this->w - $this->rMargin - $x;
}
}
$s = '';
if (is_string($border) AND (strlen($border) == 4)) {
$border = 1;
}
if ($fill OR ($border == 1)) {
if ($fill) {
$op = ($border == 1) ? 'B' : 'f';
} else {
$op = 'S';
}
if ($this->rtl) {
$xk = (($x - $w) * $k);
} else {
$xk = ($x * $k);
}
$s .= sprintf('%F %F %F %F re %s ', $xk, (($this->h - $y) * $k), ($w * $k), (-$h * $k), $op);
}
$s .= $this->getCellBorder($x, $y, $w, $h, $border);
if ($txt != '') {
$txt2 = $txt;
if ($this->isunicode) {
if (($this->CurrentFont['type'] == 'core') OR ($this->CurrentFont['type'] == 'TrueType') OR ($this->CurrentFont['type'] == 'Type1')) {
$txt2 = TCPDF_FONTS::UTF8ToLatin1($txt2, $this->isunicode, $this->CurrentFont);
} else {
$unicode = TCPDF_FONTS::UTF8StringToArray($txt, $this->isunicode, $this->CurrentFont);
$unicode = TCPDF_FONTS::utf8Bidi($unicode, '', $this->tmprtl, $this->isunicode, $this->CurrentFont);
if (defined('K_THAI_TOPCHARS') AND (K_THAI_TOPCHARS == true)) {
$numchars = count($unicode);
$longtail = array(0x0e1b, 0x0e1d, 0x0e1f);
$lowtail = array(0x0e0e, 0x0e0f);
$upvowel = array(0x0e31, 0x0e34, 0x0e35, 0x0e36, 0x0e37);
$tonemark = array(0x0e48, 0x0e49, 0x0e4a, 0x0e4b, 0x0e4c);
$lowvowel = array(0x0e38, 0x0e39, 0x0e3a);
$output = array();
for ($i = 0; $i < $numchars; $i++) {
if (($unicode[$i] >= 0x0e00) && ($unicode[$i] <= 0x0e5b)) {
$ch0 = $unicode[$i];
$ch1 = ($i > 0) ? $unicode[($i - 1)] : 0;
$ch2 = ($i > 1) ? $unicode[($i - 2)] : 0;
$chn = ($i < ($numchars - 1)) ? $unicode[($i + 1)] : 0;
if (in_array($ch0, $tonemark)) {
if ($chn == 0x0e33) {
if (in_array($ch1, $longtail)) {
$output[] = $this->replaceChar($ch0, (0xf713 + $ch0 - 0x0e48));
} else {
$output[] = $ch0;
}
} elseif (in_array($ch1, $longtail) OR (in_array($ch2, $longtail) AND in_array($ch1, $lowvowel))) {
$output[] = $this->replaceChar($ch0, (0xf705 + $ch0 - 0x0e48));
} elseif (in_array($ch1, $upvowel)) {
if (in_array($ch2, $longtail)) {
$output[] = $this->replaceChar($ch0, (0xf713 + $ch0 - 0x0e48));
} else {
$output[] = $ch0;
}
} else {
$output[] = $this->replaceChar($ch0, (0xf70a + $ch0 - 0x0e48));
}
} elseif (($ch0 == 0x0e33) AND (in_array($ch1, $longtail) OR (in_array($ch2, $longtail) AND in_array($ch1, $tonemark)))) {
if ($this->isCharDefined(0xf711) AND $this->isCharDefined(0x0e32)) {
$output[] = 0xf711;
$this->CurrentFont['subsetchars'][0xf711] = true;
$output[] = 0x0e32;
$this->CurrentFont['subsetchars'][0x0e32] = true;
} else {
$output[] = $ch0;
}
} elseif (in_array($ch1, $longtail)) {
if ($ch0 == 0x0e31) {
$output[] = $this->replaceChar($ch0, 0xf710);
} elseif (in_array($ch0, $upvowel)) {
$output[] = $this->replaceChar($ch0, (0xf701 + $ch0 - 0x0e34));
} elseif ($ch0 == 0x0e47) {
$output[] = $this->replaceChar($ch0, 0xf712);
} else {
$output[] = $ch0;
}
} elseif (in_array($ch1, $lowtail) AND in_array($ch0, $lowvowel)) {
$output[] = $this->replaceChar($ch0, (0xf718 + $ch0 - 0x0e38));
} elseif (($ch0 == 0x0e0d) AND in_array($chn, $lowvowel)) {
$output[] = $this->replaceChar($ch0, 0xf70f);
} elseif (($ch0 == 0x0e10) AND in_array($chn, $lowvowel)) {
$output[] = $this->replaceChar($ch0, 0xf700);
} else {
$output[] = $ch0;
}
} else {
$output[] = $unicode[$i];
}
}
$unicode = $output;
$this->setFontSubBuffer($this->CurrentFont['fontkey'], 'subsetchars', $this->CurrentFont['subsetchars']);
}
$txt2 = TCPDF_FONTS::arrUTF8ToUTF16BE($unicode, false);
}
}
$txt2 = TCPDF_STATIC::_escape($txt2);
$txwidth = $this->GetStringWidth($txt);
$width = $txwidth;
if ($stretch > 0) {
if ($width <= 0) {
$ratio = 1;
} else {
$ratio = (($w - $this->cell_padding['L'] - $this->cell_padding['R']) / $width);
}
if (($ratio < 1) OR (($ratio > 1) AND (($stretch % 2) == 0))) {
if ($stretch > 2) {
$this->font_spacing += ($w - $this->cell_padding['L'] - $this->cell_padding['R'] - $width) / (max(($this->GetNumChars($txt) - 1), 1) * ($this->font_stretching / 100));
} else {
$this->font_stretching *= $ratio;
}
$width = $w - $this->cell_padding['L'] - $this->cell_padding['R'];
$align = '';
}
}
if ($this->font_stretching != 100) {
$rs .= sprintf('BT %F Tz ET ', $this->font_stretching);
}
if ($this->font_spacing != 0) {
$rs .= sprintf('BT %F Tc ET ', ($this->font_spacing * $this->k));
}
if ($this->ColorFlag AND ($this->textrendermode < 4)) {
$s .= 'q '.$this->TextColor.' ';
}
$s .= sprintf('BT %d Tr %F w ET ', $this->textrendermode, ($this->textstrokewidth * $this->k));
$ns = substr_count($txt, chr(32));
$spacewidth = 0;
if (($align == 'J') AND ($ns > 0)) {
if ($this->isUnicodeFont()) {
$width = $this->GetStringWidth(str_replace(' ', '', $txt));
$spacewidth = -1000 * ($w - $width - $this->cell_padding['L'] - $this->cell_padding['R']) / ($ns?$ns:1) / ($this->FontSize?$this->FontSize:1);
if ($this->font_stretching != 100) {
$spacewidth /= ($this->font_stretching / 100);
}
$txt2 = str_replace(chr(0).chr(32), ') '.sprintf('%F', $spacewidth).' (', $txt2);
$unicode_justification = true;
} else {
$width = $txwidth;
$spacewidth = (($w - $width - $this->cell_padding['L'] - $this->cell_padding['R']) / ($ns?$ns:1)) * $this->k;
if ($this->font_stretching != 100) {
$spacewidth /= ($this->font_stretching / 100);
}
$rs .= sprintf('BT %F Tw ET ', $spacewidth);
}
$width = $w - $this->cell_padding['L'] - $this->cell_padding['R'];
}
$txt2 = str_replace("\r", ' ', $txt2);
switch ($align) {
case 'C': {
$dx = ($w - $width) / 2;
break;
}
case 'R': {
if ($this->rtl) {
$dx = $this->cell_padding['R'];
} else {
$dx = $w - $width - $this->cell_padding['R'];
}
break;
}
case 'L': {
if ($this->rtl) {
$dx = $w - $width - $this->cell_padding['L'];
} else {
$dx = $this->cell_padding['L'];
}
break;
}
case 'J':
default: {
if ($this->rtl) {
$dx = $this->cell_padding['R'];
} else {
$dx = $this->cell_padding['L'];
}
break;
}
}
if ($this->rtl) {
$xdx = $x - $dx - $width;
} else {
$xdx = $x + $dx;
}
$xdk = $xdx * $k;
$s .= sprintf('BT %F %F Td [(%s)] TJ ET', $xdk, (($this->h - $basefonty) * $k), $txt2);
if (isset($uniblock)) {
$xshift = 0;
$ty = (($this->h - $basefonty + (0.2 * $this->FontSize)) * $k);
$spw = (($w - $txwidth - $this->cell_padding['L'] - $this->cell_padding['R']) / ($ns?$ns:1));
foreach ($uniblock as $uk => $uniarr) {
if (($uk % 2) == 0) {
if ($spacewidth != 0) {
$xshift += (count(array_keys($uniarr, 32)) * $spw);
}
$xshift += $this->GetArrStringWidth($uniarr);
} else {
$topchr = TCPDF_FONTS::arrUTF8ToUTF16BE($uniarr, false);
$topchr = TCPDF_STATIC::_escape($topchr);
$s .= sprintf(' BT %F %F Td [(%s)] TJ ET', ($xdk + ($xshift * $k)), $ty, $topchr);
}
}
}
if ($this->underline) {
$s .= ' '.$this->_dounderlinew($xdx, $basefonty, $width);
}
if ($this->linethrough) {
$s .= ' '.$this->_dolinethroughw($xdx, $basefonty, $width);
}
if ($this->overline) {
$s .= ' '.$this->_dooverlinew($xdx, $basefonty, $width);
}
if ($this->ColorFlag AND ($this->textrendermode < 4)) {
$s .= ' Q';
}
if ($link) {
$this->Link($xdx, $yt, $width, ($this->FontAscent + $this->FontDescent), $link, $ns);
}
}
if ($s) {
$rs .= $s;
if ($this->font_spacing != 0) {
$rs .= ' BT 0 Tc ET';
}
if ($this->font_stretching != 100) {
$rs .= ' BT 100 Tz ET';
}
}
if (!$this->isUnicodeFont() AND ($align == 'J')) {
$rs .= ' BT 0 Tw ET';
}
$this->font_stretching = $prev_font_stretching;
$this->font_spacing = $prev_font_spacing;
$this->lasth = $h;
if ($ln > 0) {
$this->y = $y + $h + $this->cell_margin['B'];
if ($ln == 1) {
if ($this->rtl) {
$this->x = $this->w - $this->rMargin;
} else {
$this->x = $this->lMargin;
}
}
} else {
if ($this->rtl) {
$this->x = $x - $w - $this->cell_margin['L'];
} else {
$this->x = $x + $w + $this->cell_margin['R'];
}
}
$gstyles = ''.$this->linestyleWidth.' '.$this->linestyleCap.' '.$this->linestyleJoin.' '.$this->linestyleDash.' '.$this->DrawColor.' '.$this->FillColor."\n";
$rs = $gstyles.$rs;
$this->cell_padding = $prev_cell_padding;
$this->cell_margin = $prev_cell_margin;
return $rs;
}
protected function replaceChar($oldchar, $newchar) {
if ($this->isCharDefined($newchar)) {
$this->CurrentFont['subsetchars'][$newchar] = true;
return $newchar;
}
return $oldchar;
}
protected function getCellBorder($x, $y, $w, $h, $brd) {
$s = '';
if (empty($brd)) {
return $s;
}
if ($brd == 1) {
$brd = array('LRTB' => true);
}
$k = $this->k;
if ($this->rtl) {
$xeL = ($x - $w) * $k;
$xeR = $x * $k;
} else {
$xeL = $x * $k;
$xeR = ($x + $w) * $k;
}
$yeL = (($this->h - ($y + $h)) * $k);
$yeT = (($this->h - $y) * $k);
$xeT = $xeL;
$xeB = $xeR;
$yeR = $yeT;
$yeB = $yeL;
if (is_string($brd)) {
$slen = strlen($brd);
$newbrd = array();
for ($i = 0; $i < $slen; ++$i) {
$newbrd[$brd[$i]] = array('cap' => 'square', 'join' => 'miter');
}
$brd = $newbrd;
}
if (isset($brd['mode'])) {
$mode = $brd['mode'];
unset($brd['mode']);
} else {
$mode = 'normal';
}
foreach ($brd as $border => $style) {
if (is_array($style) AND !empty($style)) {
$prev_style = $this->linestyleWidth.' '.$this->linestyleCap.' '.$this->linestyleJoin.' '.$this->linestyleDash.' '.$this->DrawColor.' ';
$s .= $this->SetLineStyle($style, true)."\n";
}
switch ($mode) {
case 'ext': {
$off = (($this->LineWidth / 2) * $k);
$xL = $xeL - $off;
$xR = $xeR + $off;
$yT = $yeT + $off;
$yL = $yeL - $off;
$xT = $xL;
$xB = $xR;
$yR = $yT;
$yB = $yL;
$w += $this->LineWidth;
$h += $this->LineWidth;
break;
}
case 'int': {
$off = ($this->LineWidth / 2) * $k;
$xL = $xeL + $off;
$xR = $xeR - $off;
$yT = $yeT - $off;
$yL = $yeL + $off;
$xT = $xL;
$xB = $xR;
$yR = $yT;
$yB = $yL;
$w -= $this->LineWidth;
$h -= $this->LineWidth;
break;
}
case 'normal':
default: {
$xL = $xeL;
$xT = $xeT;
$xB = $xeB;
$xR = $xeR;
$yL = $yeL;
$yT = $yeT;
$yB = $yeB;
$yR = $yeR;
break;
}
}
if (strlen($border) == 4) {
$s .= sprintf('%F %F %F %F re S ', $xT, $yT, ($w * $k), (-$h * $k));
} elseif (strlen($border) == 3) {
if (strpos($border,'B') === false) {
$s .= sprintf('%F %F m ', $xL, $yL);
$s .= sprintf('%F %F l ', $xT, $yT);
$s .= sprintf('%F %F l ', $xR, $yR);
$s .= sprintf('%F %F l ', $xB, $yB);
$s .= 'S ';
} elseif (strpos($border,'L') === false) {
$s .= sprintf('%F %F m ', $xT, $yT);
$s .= sprintf('%F %F l ', $xR, $yR);
$s .= sprintf('%F %F l ', $xB, $yB);
$s .= sprintf('%F %F l ', $xL, $yL);
$s .= 'S ';
} elseif (strpos($border,'T') === false) {
$s .= sprintf('%F %F m ', $xR, $yR);
$s .= sprintf('%F %F l ', $xB, $yB);
$s .= sprintf('%F %F l ', $xL, $yL);
$s .= sprintf('%F %F l ', $xT, $yT);
$s .= 'S ';
} elseif (strpos($border,'R') === false) {
$s .= sprintf('%F %F m ', $xB, $yB);
$s .= sprintf('%F %F l ', $xL, $yL);
$s .= sprintf('%F %F l ', $xT, $yT);
$s .= sprintf('%F %F l ', $xR, $yR);
$s .= 'S ';
}
} elseif (strlen($border) == 2) {
if ((strpos($border,'L') !== false) AND (strpos($border,'T') !== false)) {
$s .= sprintf('%F %F m ', $xL, $yL);
$s .= sprintf('%F %F l ', $xT, $yT);
$s .= sprintf('%F %F l ', $xR, $yR);
$s .= 'S ';
} elseif ((strpos($border,'T') !== false) AND (strpos($border,'R') !== false)) {
$s .= sprintf('%F %F m ', $xT, $yT);
$s .= sprintf('%F %F l ', $xR, $yR);
$s .= sprintf('%F %F l ', $xB, $yB);
$s .= 'S ';
} elseif ((strpos($border,'R') !== false) AND (strpos($border,'B') !== false)) {
$s .= sprintf('%F %F m ', $xR, $yR);
$s .= sprintf('%F %F l ', $xB, $yB);
$s .= sprintf('%F %F l ', $xL, $yL);
$s .= 'S ';
} elseif ((strpos($border,'B') !== false) AND (strpos($border,'L') !== false)) {
$s .= sprintf('%F %F m ', $xB, $yB);
$s .= sprintf('%F %F l ', $xL, $yL);
$s .= sprintf('%F %F l ', $xT, $yT);
$s .= 'S ';
} elseif ((strpos($border,'L') !== false) AND (strpos($border,'R') !== false)) {
$s .= sprintf('%F %F m ', $xL, $yL);
$s .= sprintf('%F %F l ', $xT, $yT);
$s .= 'S ';
$s .= sprintf('%F %F m ', $xR, $yR);
$s .= sprintf('%F %F l ', $xB, $yB);
$s .= 'S ';
} elseif ((strpos($border,'T') !== false) AND (strpos($border,'B') !== false)) {
$s .= sprintf('%F %F m ', $xT, $yT);
$s .= sprintf('%F %F l ', $xR, $yR);
$s .= 'S ';
$s .= sprintf('%F %F m ', $xB, $yB);
$s .= sprintf('%F %F l ', $xL, $yL);
$s .= 'S ';
}
} else {
if (strpos($border,'L') !== false) {
$s .= sprintf('%F %F m ', $xL, $yL);
$s .= sprintf('%F %F l ', $xT, $yT);
$s .= 'S ';
} elseif (strpos($border,'T') !== false) {
$s .= sprintf('%F %F m ', $xT, $yT);
$s .= sprintf('%F %F l ', $xR, $yR);
$s .= 'S ';
} elseif (strpos($border,'R') !== false) {
$s .= sprintf('%F %F m ', $xR, $yR);
$s .= sprintf('%F %F l ', $xB, $yB);
$s .= 'S ';
} elseif (strpos($border,'B') !== false) {
$s .= sprintf('%F %F m ', $xB, $yB);
$s .= sprintf('%F %F l ', $xL, $yL);
$s .= 'S ';
}
}
if (is_array($style) AND !empty($style)) {
$s .= "\n".$this->linestyleWidth.' '.$this->linestyleCap.' '.$this->linestyleJoin.' '.$this->linestyleDash.' '.$this->DrawColor."\n";
}
}
return $s;
}
public function MultiCell($w, $h, $txt, $border=0, $align='J', $fill=false, $ln=1, $x='', $y='', $reseth=true, $stretch=0, $ishtml=false, $autopadding=true, $maxh=0, $valign='T', $fitcell=false) {
$prev_cell_margin = $this->cell_margin;
$prev_cell_padding = $this->cell_padding;
$this->adjustCellPadding($border);
$mc_padding = $this->cell_padding;
$mc_margin = $this->cell_margin;
$this->cell_padding['T'] = 0;
$this->cell_padding['B'] = 0;
$this->setCellMargins(0, 0, 0, 0);
if (TCPDF_STATIC::empty_string($this->lasth) OR $reseth) {
$this->resetLastH();
}
if (!TCPDF_STATIC::empty_string($y)) {
$this->SetY($y);
} else {
$y = $this->GetY();
}
$resth = 0;
if (($h > 0) AND $this->inPageBody() AND (($y + $h + $mc_margin['T'] + $mc_margin['B']) > $this->PageBreakTrigger)) {
$newh = ($this->PageBreakTrigger - $y);
$resth = ($h - $newh);
$h = $newh;
}
$startpage = $this->page;
$startcolumn = $this->current_column;
if (!TCPDF_STATIC::empty_string($x)) {
$this->SetX($x);
} else {
$x = $this->GetX();
}
list($x, $y) = $this->checkPageRegions(0, $x, $y);
$oy = $y + $mc_margin['T'];
if ($this->rtl) {
$ox = ($this->w - $x - $mc_margin['R']);
} else {
$ox = ($x + $mc_margin['L']);
}
$this->x = $ox;
$this->y = $oy;
if (TCPDF_STATIC::empty_string($w) OR ($w <= 0)) {
if ($this->rtl) {
$w = ($this->x - $this->lMargin - $mc_margin['L']);
} else {
$w = ($this->w - $this->x - $this->rMargin - $mc_margin['R']);
}
}
$lMargin = $this->lMargin;
$rMargin = $this->rMargin;
if ($this->rtl) {
$this->rMargin = ($this->w - $this->x);
$this->lMargin = ($this->x - $w);
} else {
$this->lMargin = ($this->x);
$this->rMargin = ($this->w - $this->x - $w);
}
$this->clMargin = $this->lMargin;
$this->crMargin = $this->rMargin;
if ($autopadding) {
$this->y += $mc_padding['T'];
}
if ($ishtml) {
$this->writeHTML($txt, true, false, $reseth, true, $align);
$nl = 1;
} else {
$prev_FontSizePt = $this->FontSizePt;
if ($fitcell) {
$tobottom = ($this->h - $this->y - $this->bMargin - $this->cell_padding['T'] - $this->cell_padding['B']);
$h = $maxh = max(min($h, $tobottom), min($maxh, $tobottom));
}
if ($maxh > 0) {
$text_height = $this->getStringHeight($w, $txt, $reseth, $autopadding, $mc_padding, $border);
if ($fitcell AND ($text_height > $maxh) AND ($this->FontSizePt > 1)) {
$fmin = 1;
$fmax = $this->FontSizePt;
$diff_epsilon = (1 / $this->k);
$maxit = (2 * min(100, max(10, intval($fmax))));
while ($maxit >= 0) {
$fmid = (($fmax + $fmin) / 2);
$this->SetFontSize($fmid, false);
$this->resetLastH();
$text_height = $this->getStringHeight($w, $txt, $reseth, $autopadding, $mc_padding, $border);
$diff = ($maxh - $text_height);
if ($diff >= 0) {
if ($diff <= $diff_epsilon) {
break;
}
$fmin = $fmid;
} else {
$fmax = $fmid;
}
--$maxit;
}
if ($maxit < 0) {
$this->SetFontSize($fmin);
$this->resetLastH();
$text_height = $this->getStringHeight($w, $txt, $reseth, $autopadding, $mc_padding, $border);
} else {
$this->SetFontSize($fmid);
$this->resetLastH();
}
}
if ($text_height < $maxh) {
if ($valign == 'M') {
$this->y += (($maxh - $text_height) / 2);
} elseif ($valign == 'B') {
$this->y += ($maxh - $text_height);
}
}
}
$nl = $this->Write($this->lasth, $txt, '', 0, $align, true, $stretch, false, true, $maxh, 0, $mc_margin);
if ($fitcell) {
$this->SetFontSize($prev_FontSizePt);
}
}
if ($autopadding) {
$this->y += $mc_padding['B'];
}
$currentY = $this->y;
$endpage = $this->page;
if ($resth > 0) {
$skip = ($endpage - $startpage);
$tmpresth = $resth;
while ($tmpresth > 0) {
if ($skip <= 0) {
$this->checkPageBreak($this->PageBreakTrigger + 1);
}
if ($this->num_columns > 1) {
$tmpresth -= ($this->h - $this->y - $this->bMargin);
} else {
$tmpresth -= ($this->h - $this->tMargin - $this->bMargin);
}
--$skip;
}
$currentY = $this->y;
$endpage = $this->page;
}
$endcolumn = $this->current_column;
if ($this->num_columns == 0) {
$this->num_columns = 1;
}
$check_page_regions = $this->check_page_regions;
$this->check_page_regions = false;
$border_start = TCPDF_STATIC::getBorderMode($border, $position='start', $this->opencell);
$border_end = TCPDF_STATIC::getBorderMode($border, $position='end', $this->opencell);
$border_middle = TCPDF_STATIC::getBorderMode($border, $position='middle', $this->opencell);
for ($page = $startpage; $page <= $endpage; ++$page) {
$ccode = '';
$this->setPage($page);
if ($this->num_columns < 2) {
$this->SetX($x);
$this->y = $this->tMargin;
}
if ($page > $startpage) {
if (($this->rtl) AND ($this->pagedim[$page]['orm'] != $this->pagedim[$startpage]['orm'])) {
$this->x -= ($this->pagedim[$page]['orm'] - $this->pagedim[$startpage]['orm']);
} elseif ((!$this->rtl) AND ($this->pagedim[$page]['olm'] != $this->pagedim[$startpage]['olm'])) {
$this->x += ($this->pagedim[$page]['olm'] - $this->pagedim[$startpage]['olm']);
}
}
if ($startpage == $endpage) {
for ($column = $startcolumn; $column <= $endcolumn; ++$column) {
if ($column != $this->current_column) {
$this->selectColumn($column);
}
if ($this->rtl) {
$this->x -= $mc_margin['R'];
} else {
$this->x += $mc_margin['L'];
}
if ($startcolumn == $endcolumn) {
$cborder = $border;
$h = max($h, ($currentY - $oy));
$this->y = $oy;
} elseif ($column == $startcolumn) {
$cborder = $border_start;
$this->y = $oy;
$h = $this->h - $this->y - $this->bMargin;
} elseif ($column == $endcolumn) {
$cborder = $border_end;
$h = $currentY - $this->y;
if ($resth > $h) {
$h = $resth;
}
} else {
$cborder = $border_middle;
$h = $this->h - $this->y - $this->bMargin;
$resth -= $h;
}
$ccode .= $this->getCellCode($w, $h, '', $cborder, 1, '', $fill, '', 0, true)."\n";
}
} elseif ($page == $startpage) {
for ($column = $startcolumn; $column < $this->num_columns; ++$column) {
if ($column != $this->current_column) {
$this->selectColumn($column);
}
if ($this->rtl) {
$this->x -= $mc_margin['R'];
} else {
$this->x += $mc_margin['L'];
}
if ($column == $startcolumn) {
$cborder = $border_start;
$this->y = $oy;
$h = $this->h - $this->y - $this->bMargin;
} else {
$cborder = $border_middle;
$h = $this->h - $this->y - $this->bMargin;
$resth -= $h;
}
$ccode .= $this->getCellCode($w, $h, '', $cborder, 1, '', $fill, '', 0, true)."\n";
}
} elseif ($page == $endpage) {
for ($column = 0; $column <= $endcolumn; ++$column) {
if ($column != $this->current_column) {
$this->selectColumn($column);
}
if ($this->rtl) {
$this->x -= $mc_margin['R'];
} else {
$this->x += $mc_margin['L'];
}
if ($column == $endcolumn) {
$cborder = $border_end;
$h = $currentY - $this->y;
if ($resth > $h) {
$h = $resth;
}
} else {
$cborder = $border_middle;
$h = $this->h - $this->y - $this->bMargin;
$resth -= $h;
}
$ccode .= $this->getCellCode($w, $h, '', $cborder, 1, '', $fill, '', 0, true)."\n";
}
} else {
for ($column = 0; $column < $this->num_columns; ++$column) {
$this->selectColumn($column);
if ($this->rtl) {
$this->x -= $mc_margin['R'];
} else {
$this->x += $mc_margin['L'];
}
$cborder = $border_middle;
$h = $this->h - $this->y - $this->bMargin;
$resth -= $h;
$ccode .= $this->getCellCode($w, $h, '', $cborder, 1, '', $fill, '', 0, true)."\n";
}
}
if ($cborder OR $fill) {
$offsetlen = strlen($ccode);
if ($this->inxobj) {
if (end($this->xobjects[$this->xobjid]['transfmrk']) !== false) {
$pagemarkkey = key($this->xobjects[$this->xobjid]['transfmrk']);
$pagemark = $this->xobjects[$this->xobjid]['transfmrk'][$pagemarkkey];
$this->xobjects[$this->xobjid]['transfmrk'][$pagemarkkey] += $offsetlen;
} else {
$pagemark = $this->xobjects[$this->xobjid]['intmrk'];
$this->xobjects[$this->xobjid]['intmrk'] += $offsetlen;
}
$pagebuff = $this->xobjects[$this->xobjid]['outdata'];
$pstart = substr($pagebuff, 0, $pagemark);
$pend = substr($pagebuff, $pagemark);
$this->xobjects[$this->xobjid]['outdata'] = $pstart.$ccode.$pend;
} else {
if (end($this->transfmrk[$this->page]) !== false) {
$pagemarkkey = key($this->transfmrk[$this->page]);
$pagemark = $this->transfmrk[$this->page][$pagemarkkey];
$this->transfmrk[$this->page][$pagemarkkey] += $offsetlen;
} elseif ($this->InFooter) {
$pagemark = $this->footerpos[$this->page];
$this->footerpos[$this->page] += $offsetlen;
} else {
$pagemark = $this->intmrk[$this->page];
$this->intmrk[$this->page] += $offsetlen;
}
$pagebuff = $this->getPageBuffer($this->page);
$pstart = substr($pagebuff, 0, $pagemark);
$pend = substr($pagebuff, $pagemark);
$this->setPageBuffer($this->page, $pstart.$ccode.$pend);
}
}
}
$this->check_page_regions = $check_page_regions;
$currentY = $this->GetY();
if ($this->num_columns > 1) {
$this->selectColumn();
} else {
$this->lMargin = $lMargin;
$this->rMargin = $rMargin;
if ($this->page > $startpage) {
$dl = ($this->pagedim[$this->page]['olm'] - $this->pagedim[$startpage]['olm']);
$dr = ($this->pagedim[$this->page]['orm'] - $this->pagedim[$startpage]['orm']);
if (($dl != 0) OR ($dr != 0)) {
$this->lMargin += $dl;
$this->rMargin += $dr;
}
}
}
if ($ln > 0) {
$this->SetY($currentY + $mc_margin['B']);
if ($ln == 2) {
$this->SetX($x + $w + $mc_margin['L'] + $mc_margin['R']);
}
} else {
$this->setPage($startpage);
$this->y = $y;
$this->SetX($x + $w + $mc_margin['L'] + $mc_margin['R']);
}
$this->setContentMark();
$this->cell_padding = $prev_cell_padding;
$this->cell_margin = $prev_cell_margin;
$this->clMargin = $this->lMargin;
$this->crMargin = $this->rMargin;
return $nl;
}
public function getNumLines($txt, $w=0, $reseth=false, $autopadding=true, $cellpadding='', $border=0) {
if ($txt === NULL) {
return 0;
}
if ($txt === '') {
return 1;
}
$prev_cell_padding = $this->cell_padding;
$prev_lasth = $this->lasth;
if (is_array($cellpadding)) {
$this->cell_padding = $cellpadding;
}
$this->adjustCellPadding($border);
if (TCPDF_STATIC::empty_string($w) OR ($w <= 0)) {
if ($this->rtl) {
$w = $this->x - $this->lMargin;
} else {
$w = $this->w - $this->rMargin - $this->x;
}
}
$wmax = $w - $this->cell_padding['L'] - $this->cell_padding['R'];
if ($reseth) {
$this->resetLastH();
}
$lines = 1;
$sum = 0;
$chars = TCPDF_FONTS::utf8Bidi(TCPDF_FONTS::UTF8StringToArray($txt, $this->isunicode, $this->CurrentFont), $txt, $this->tmprtl, $this->isunicode, $this->CurrentFont);
$charsWidth = $this->GetArrStringWidth($chars, '', '', 0, true);
$length = count($chars);
$lastSeparator = -1;
for ($i = 0; $i < $length; ++$i) {
$c = $chars[$i];
$charWidth = $charsWidth[$i];
if (($c != 160)
AND (($c == 173)
OR preg_match($this->re_spaces, TCPDF_FONTS::unichr($c, $this->isunicode))
OR (($c == 45)
AND ($i > 0) AND ($i < ($length - 1))
AND @preg_match('/[\p{L}]/'.$this->re_space['m'], TCPDF_FONTS::unichr($chars[($i - 1)], $this->isunicode))
AND @preg_match('/[\p{L}]/'.$this->re_space['m'], TCPDF_FONTS::unichr($chars[($i + 1)], $this->isunicode))
)
)
) {
$lastSeparator = $i;
}
if ((($sum + $charWidth) > $wmax) OR ($c == 10)) {
++$lines;
if ($c == 10) {
$lastSeparator = -1;
$sum = 0;
} elseif ($lastSeparator != -1) {
$i = $lastSeparator;
$lastSeparator = -1;
$sum = 0;
} else {
$sum = $charWidth;
}
} else {
$sum += $charWidth;
}
}
if ($chars[($length - 1)] == 10) {
--$lines;
}
$this->cell_padding = $prev_cell_padding;
$this->lasth = $prev_lasth;
return $lines;
}
public function getStringHeight($w, $txt, $reseth=false, $autopadding=true, $cellpadding='', $border=0) {
$prev_cell_padding = $this->cell_padding;
$prev_lasth = $this->lasth;
if (is_array($cellpadding)) {
$this->cell_padding = $cellpadding;
}
$this->adjustCellPadding($border);
$lines = $this->getNumLines($txt, $w, $reseth, $autopadding, $cellpadding, $border);
$height = $this->getCellHeight(($lines * $this->FontSize), $autopadding);
$this->cell_padding = $prev_cell_padding;
$this->lasth = $prev_lasth;
return $height;
}
public function Write($h, $txt, $link='', $fill=false, $align='', $ln=false, $stretch=0, $firstline=false, $firstblock=false, $maxh=0, $wadj=0, $margin='') {
list($this->x, $this->y) = $this->checkPageRegions($h, $this->x, $this->y);
if (strlen($txt) == 0) {
$txt = ' ';
}
if ($margin === '') {
$margin = $this->cell_margin;
}
$s = str_replace("\r", '', $txt);
if (preg_match(TCPDF_FONT_DATA::$uni_RE_PATTERN_ARABIC, $s)) {
$arabic = true;
} else {
$arabic = false;
}
if ($arabic OR ($this->tmprtl == 'R') OR preg_match(TCPDF_FONT_DATA::$uni_RE_PATTERN_RTL, $s)) {
$rtlmode = true;
} else {
$rtlmode = false;
}
$chrwidth = $this->GetCharWidth(46);
$chars = TCPDF_FONTS::UTF8StringToArray($s, $this->isunicode, $this->CurrentFont);
$chrw = $this->GetArrStringWidth($chars, '', '', 0, true);
array_walk($chrw, array($this, 'getRawCharWidth'));
$maxchwidth = max($chrw);
$uchars = TCPDF_FONTS::UTF8ArrayToUniArray($chars, $this->isunicode);
$nb = count($chars);
$shy_replacement = 45;
$shy_replacement_char = TCPDF_FONTS::unichr($shy_replacement, $this->isunicode);
$shy_replacement_width = $this->GetCharWidth($shy_replacement);
$pw = $w = $this->w - $this->lMargin - $this->rMargin;
if ($this->rtl) {
$w = $this->x - $this->lMargin;
} else {
$w = $this->w - $this->rMargin - $this->x;
}
$wmax = ($w - $wadj);
if (!$firstline) {
$wmax -= ($this->cell_padding['L'] + $this->cell_padding['R']);
}
if ((!$firstline) AND (($chrwidth > $wmax) OR ($maxchwidth > $wmax))) {
return '';
}
$row_height = max($h, $this->getCellHeight($this->FontSize));
$maxy = $this->y + $maxh - max($row_height, $h);
$start_page = $this->page;
$i = 0;
$j = 0;
$sep = -1;
$prevsep = $sep;
$shy = false;
$prevshy = $shy;
$l = 0;
$nl = 0;
$linebreak = false;
$pc = 0;
while ($i < $nb) {
if (($maxh > 0) AND ($this->y > $maxy) ) {
break;
}
$c = $chars[$i];
if ($c == 10) {
if ($align == 'J') {
if ($this->rtl) {
$talign = 'R';
} else {
$talign = 'L';
}
} else {
$talign = $align;
}
$tmpstr = TCPDF_FONTS::UniArrSubString($uchars, $j, $i);
if ($firstline) {
$startx = $this->x;
$tmparr = array_slice($chars, $j, ($i - $j));
if ($rtlmode) {
$tmparr = TCPDF_FONTS::utf8Bidi($tmparr, $tmpstr, $this->tmprtl, $this->isunicode, $this->CurrentFont);
}
$linew = $this->GetArrStringWidth($tmparr);
unset($tmparr);
if ($this->rtl) {
$this->endlinex = $startx - $linew;
} else {
$this->endlinex = $startx + $linew;
}
$w = $linew;
$tmpcellpadding = $this->cell_padding;
if ($maxh == 0) {
$this->SetCellPadding(0);
}
}
if ($firstblock AND $this->isRTLTextDir()) {
$tmpstr = $this->stringRightTrim($tmpstr);
}
if (!empty($tmpstr) OR ($this->y < ($this->PageBreakTrigger - $row_height))) {
$this->Cell($w, $h, $tmpstr, 0, 1, $talign, $fill, $link, $stretch);
}
unset($tmpstr);
if ($firstline) {
$this->cell_padding = $tmpcellpadding;
return (TCPDF_FONTS::UniArrSubString($uchars, $i));
}
++$nl;
$j = $i + 1;
$l = 0;
$sep = -1;
$prevsep = $sep;
$shy = false;
if ((($this->y + $this->lasth) > $this->PageBreakTrigger) AND ($this->inPageBody())) {
$this->AcceptPageBreak();
if ($this->rtl) {
$this->x -= $margin['R'];
} else {
$this->x += $margin['L'];
}
$this->lMargin += $margin['L'];
$this->rMargin += $margin['R'];
}
$w = $this->getRemainingWidth();
$wmax = ($w - $this->cell_padding['L'] - $this->cell_padding['R']);
} else {
if (($c != 160)
AND (($c == 173)
OR preg_match($this->re_spaces, TCPDF_FONTS::unichr($c, $this->isunicode))
OR (($c == 45)
AND ($i < ($nb - 1))
AND @preg_match('/[\p{L}]/'.$this->re_space['m'], TCPDF_FONTS::unichr($pc, $this->isunicode))
AND @preg_match('/[\p{L}]/'.$this->re_space['m'], TCPDF_FONTS::unichr($chars[($i + 1)], $this->isunicode))
)
)
) {
$prevsep = $sep;
$sep = $i;
if (($c == 173) OR ($c == 45)) {
$prevshy = $shy;
$shy = true;
if ($pc == 45) {
$tmp_shy_replacement_width = 0;
$tmp_shy_replacement_char = '';
} else {
$tmp_shy_replacement_width = $shy_replacement_width;
$tmp_shy_replacement_char = $shy_replacement_char;
}
} else {
$shy = false;
}
}
if ($this->isUnicodeFont() AND ($arabic)) {
$l = $this->GetArrStringWidth(TCPDF_FONTS::utf8Bidi(array_slice($chars, $j, ($i - $j)), '', $this->tmprtl, $this->isunicode, $this->CurrentFont));
} else {
$l += $this->GetCharWidth($c);
}
if (($l > $wmax) OR (($c == 173) AND (($l + $tmp_shy_replacement_width) >= $wmax))) {
if (($c == 173) AND (($l + $tmp_shy_replacement_width) > $wmax)) {
$sep = $prevsep;
$shy = $prevshy;
}
if ($sep == -1) {
if (($this->rtl AND ($this->x <= ($this->w - $this->rMargin - $this->cell_padding['R'] - $margin['R'] - $chrwidth)))
OR ((!$this->rtl) AND ($this->x >= ($this->lMargin + $this->cell_padding['L'] + $margin['L'] + $chrwidth)))) {
$this->Cell($w, $h, '', 0, 1);
$linebreak = true;
if ($firstline) {
return (TCPDF_FONTS::UniArrSubString($uchars, $j));
}
} else {
$tmpstr = TCPDF_FONTS::UniArrSubString($uchars, $j, $i);
if ($firstline) {
$startx = $this->x;
$tmparr = array_slice($chars, $j, ($i - $j));
if ($rtlmode) {
$tmparr = TCPDF_FONTS::utf8Bidi($tmparr, $tmpstr, $this->tmprtl, $this->isunicode, $this->CurrentFont);
}
$linew = $this->GetArrStringWidth($tmparr);
unset($tmparr);
if ($this->rtl) {
$this->endlinex = $startx - $linew;
} else {
$this->endlinex = $startx + $linew;
}
$w = $linew;
$tmpcellpadding = $this->cell_padding;
if ($maxh == 0) {
$this->SetCellPadding(0);
}
}
if ($firstblock AND $this->isRTLTextDir()) {
$tmpstr = $this->stringRightTrim($tmpstr);
}
$this->Cell($w, $h, $tmpstr, 0, 1, $align, $fill, $link, $stretch);
unset($tmpstr);
if ($firstline) {
$this->cell_padding = $tmpcellpadding;
return (TCPDF_FONTS::UniArrSubString($uchars, $i));
}
$j = $i;
--$i;
}
} else {
if ($this->rtl AND (!$firstblock) AND ($sep < $i)) {
$endspace = 1;
} else {
$endspace = 0;
}
$strrest = TCPDF_FONTS::UniArrSubString($uchars, ($sep + $endspace));
$nextstr = TCPDF_STATIC::pregSplit('/'.$this->re_space['p'].'/', $this->re_space['m'], $this->stringTrim($strrest));
if (isset($nextstr[0]) AND ($this->GetStringWidth($nextstr[0]) > $pw)) {
$tmpstr = TCPDF_FONTS::UniArrSubString($uchars, $j, $i);
if ($firstline) {
$startx = $this->x;
$tmparr = array_slice($chars, $j, ($i - $j));
if ($rtlmode) {
$tmparr = TCPDF_FONTS::utf8Bidi($tmparr, $tmpstr, $this->tmprtl, $this->isunicode, $this->CurrentFont);
}
$linew = $this->GetArrStringWidth($tmparr);
unset($tmparr);
if ($this->rtl) {
$this->endlinex = ($startx - $linew);
} else {
$this->endlinex = ($startx + $linew);
}
$w = $linew;
$tmpcellpadding = $this->cell_padding;
if ($maxh == 0) {
$this->SetCellPadding(0);
}
}
if ($firstblock AND $this->isRTLTextDir()) {
$tmpstr = $this->stringRightTrim($tmpstr);
}
$this->Cell($w, $h, $tmpstr, 0, 1, $align, $fill, $link, $stretch);
unset($tmpstr);
if ($firstline) {
$this->cell_padding = $tmpcellpadding;
return (TCPDF_FONTS::UniArrSubString($uchars, $i));
}
$j = $i;
--$i;
} else {
if ($shy) {
$shy_width = $tmp_shy_replacement_width;
if ($this->rtl) {
$shy_char_left = $tmp_shy_replacement_char;
$shy_char_right = '';
} else {
$shy_char_left = '';
$shy_char_right = $tmp_shy_replacement_char;
}
} else {
$shy_width = 0;
$shy_char_left = '';
$shy_char_right = '';
}
$tmpstr = TCPDF_FONTS::UniArrSubString($uchars, $j, ($sep + $endspace));
if ($firstline) {
$startx = $this->x;
$tmparr = array_slice($chars, $j, (($sep + $endspace) - $j));
if ($rtlmode) {
$tmparr = TCPDF_FONTS::utf8Bidi($tmparr, $tmpstr, $this->tmprtl, $this->isunicode, $this->CurrentFont);
}
$linew = $this->GetArrStringWidth($tmparr);
unset($tmparr);
if ($this->rtl) {
$this->endlinex = $startx - $linew - $shy_width;
} else {
$this->endlinex = $startx + $linew + $shy_width;
}
$w = $linew;
$tmpcellpadding = $this->cell_padding;
if ($maxh == 0) {
$this->SetCellPadding(0);
}
}
if ($firstblock AND $this->isRTLTextDir()) {
$tmpstr = $this->stringRightTrim($tmpstr);
}
$this->Cell($w, $h, $shy_char_left.$tmpstr.$shy_char_right, 0, 1, $align, $fill, $link, $stretch);
unset($tmpstr);
if ($firstline) {
if ($chars[$sep] == 45) {
$endspace += 1;
}
$this->cell_padding = $tmpcellpadding;
return (TCPDF_FONTS::UniArrSubString($uchars, ($sep + $endspace)));
}
$i = $sep;
$sep = -1;
$shy = false;
$j = ($i + 1);
}
}
if ((($this->y + $this->lasth) > $this->PageBreakTrigger) AND ($this->inPageBody())) {
$this->AcceptPageBreak();
if ($this->rtl) {
$this->x -= $margin['R'];
} else {
$this->x += $margin['L'];
}
$this->lMargin += $margin['L'];
$this->rMargin += $margin['R'];
}
$w = $this->getRemainingWidth();
$wmax = $w - $this->cell_padding['L'] - $this->cell_padding['R'];
if ($linebreak) {
$linebreak = false;
} else {
++$nl;
$l = 0;
}
}
}
$pc = $c;
++$i;
}
if ($l > 0) {
switch ($align) {
case 'J':
case 'C': {
$w = $w;
break;
}
case 'L': {
if ($this->rtl) {
$w = $w;
} else {
$w = $l;
}
break;
}
case 'R': {
if ($this->rtl) {
$w = $l;
} else {
$w = $w;
}
break;
}
default: {
$w = $l;
break;
}
}
$tmpstr = TCPDF_FONTS::UniArrSubString($uchars, $j, $nb);
if ($firstline) {
$startx = $this->x;
$tmparr = array_slice($chars, $j, ($nb - $j));
if ($rtlmode) {
$tmparr = TCPDF_FONTS::utf8Bidi($tmparr, $tmpstr, $this->tmprtl, $this->isunicode, $this->CurrentFont);
}
$linew = $this->GetArrStringWidth($tmparr);
unset($tmparr);
if ($this->rtl) {
$this->endlinex = $startx - $linew;
} else {
$this->endlinex = $startx + $linew;
}
$w = $linew;
$tmpcellpadding = $this->cell_padding;
if ($maxh == 0) {
$this->SetCellPadding(0);
}
}
if ($firstblock AND $this->isRTLTextDir()) {
$tmpstr = $this->stringRightTrim($tmpstr);
}
$this->Cell($w, $h, $tmpstr, 0, $ln, $align, $fill, $link, $stretch);
unset($tmpstr);
if ($firstline) {
$this->cell_padding = $tmpcellpadding;
return (TCPDF_FONTS::UniArrSubString($uchars, $nb));
}
++$nl;
}
if ($firstline) {
return '';
}
return $nl;
}
protected function getRemainingWidth() {
list($this->x, $this->y) = $this->checkPageRegions(0, $this->x, $this->y);
if ($this->rtl) {
return ($this->x - $this->lMargin);
} else {
return ($this->w - $this->rMargin - $this->x);
}
}
protected function fitBlock($w, $h, $x, $y, $fitonpage=false) {
if ($w <= 0) {
$w = ($this->w - $this->lMargin - $this->rMargin);
if ($w <= 0) {
$w = 1;
}
}
if ($h <= 0) {
$h = ($this->PageBreakTrigger - $this->tMargin);
if ($h <= 0) {
$h = 1;
}
}
if ($fitonpage OR $this->AutoPageBreak) {
$ratio_wh = ($w / $h);
if ($h > ($this->PageBreakTrigger - $this->tMargin)) {
$h = $this->PageBreakTrigger - $this->tMargin;
$w = ($h * $ratio_wh);
}
if ($fitonpage) {
$maxw = ($this->w - $this->lMargin - $this->rMargin);
if ($w > $maxw) {
$w = $maxw;
$h = ($w / $ratio_wh);
}
}
}
$prev_x = $this->x;
$prev_y = $this->y;
if ($this->checkPageBreak($h, $y) OR ($this->y < $prev_y)) {
$y = $this->y;
if ($this->rtl) {
$x += ($prev_x - $this->x);
} else {
$x += ($this->x - $prev_x);
}
$this->newline = true;
}
if ($fitonpage) {
$ratio_wh = ($w / $h);
if (($y + $h) > $this->PageBreakTrigger) {
$h = $this->PageBreakTrigger - $y;
$w = ($h * $ratio_wh);
}
if ((!$this->rtl) AND (($x + $w) > ($this->w - $this->rMargin))) {
$w = $this->w - $this->rMargin - $x;
$h = ($w / $ratio_wh);
} elseif (($this->rtl) AND (($x - $w) < ($this->lMargin))) {
$w = $x - $this->lMargin;
$h = ($w / $ratio_wh);
}
}
return array($w, $h, $x, $y);
}
public function Image($file, $x='', $y='', $w=0, $h=0, $type='', $link='', $align='', $resize=false, $dpi=300, $palign='', $ismask=false, $imgmask=false, $border=0, $fitbox=false, $hidden=false, $fitonpage=false, $alt=false, $altimgs=array()) {
if ($this->state != 2) {
return;
}
if (strcmp($x, '') === 0) {
$x = $this->x;
}
if (strcmp($y, '') === 0) {
$y = $this->y;
}
list($x, $y) = $this->checkPageRegions($h, $x, $y);
$exurl = '';
$imsize = FALSE;
if ($file[0] === '@') {
$imgdata = substr($file, 1);
} else {
if ($file[0] === '*') {
$file = substr($file, 1);
$exurl = $file;
}
if (!@file_exists($file)) {
$tfile = str_replace(' ', '%20', $file);
if (@file_exists($tfile)) {
$file = $tfile;
}
}
if (($imsize = @getimagesize($file)) === FALSE) {
if (in_array($file, $this->imagekeys)) {
$info = $this->getImageBuffer($file);
$imsize = array($info['w'], $info['h']);
} elseif (strpos($file, '__tcpdf_'.$this->file_id.'_img') === FALSE) {
$imgdata = TCPDF_STATIC::fileGetContents($file);
}
}
}
if (!empty($imgdata)) {
$original_file = $file;
$file = TCPDF_STATIC::getObjFilename('img', $this->file_id);
$fp = TCPDF_STATIC::fopenLocal($file, 'w');
if (!$fp) {
$this->Error('Unable to write file: '.$file);
}
fwrite($fp, $imgdata);
fclose($fp);
unset($imgdata);
$imsize = @getimagesize($file);
if ($imsize === FALSE) {
unlink($file);
$file = $original_file;
}
}
if ($imsize === FALSE) {
if (($w > 0) AND ($h > 0)) {
$pw = $this->getHTMLUnitToUnits($w, 0, $this->pdfunit, true) * $this->imgscale * $this->k;
$ph = $this->getHTMLUnitToUnits($h, 0, $this->pdfunit, true) * $this->imgscale * $this->k;
$imsize = array($pw, $ph);
} else {
$this->Error('[Image] Unable to get the size of the image: '.$file);
}
}
$filehash = md5($file);
list($pixw, $pixh) = $imsize;
if (($w <= 0) AND ($h <= 0)) {
$w = $this->pixelsToUnits($pixw);
$h = $this->pixelsToUnits($pixh);
} elseif ($w <= 0) {
$w = $h * $pixw / $pixh;
} elseif ($h <= 0) {
$h = $w * $pixh / $pixw;
} elseif (($fitbox !== false) AND ($w > 0) AND ($h > 0)) {
if (strlen($fitbox) !== 2) {
$fitbox = '--';
}
if ((($w * $pixh) / ($h * $pixw)) < 1) {
$oldh = $h;
$h = $w * $pixh / $pixw;
$hdiff = ($oldh - $h);
switch (strtoupper($fitbox[1])) {
case 'T': {
break;
}
case 'M': {
$y += ($hdiff / 2);
break;
}
case 'B': {
$y += $hdiff;
break;
}
}
} else {
$oldw = $w;
$w = $h * $pixw / $pixh;
$wdiff = ($oldw - $w);
switch (strtoupper($fitbox[0])) {
case 'L': {
if ($this->rtl) {
$x -= $wdiff;
}
break;
}
case 'C': {
if ($this->rtl) {
$x -= ($wdiff / 2);
} else {
$x += ($wdiff / 2);
}
break;
}
case 'R': {
if (!$this->rtl) {
$x += $wdiff;
}
break;
}
}
}
}
list($w, $h, $x, $y) = $this->fitBlock($w, $h, $x, $y, $fitonpage);
$neww = round($w * $this->k * $dpi / $this->dpi);
$newh = round($h * $this->k * $dpi / $this->dpi);
$newsize = ($neww * $newh);
$pixsize = ($pixw * $pixh);
if (intval($resize) == 2) {
$resize = true;
} elseif ($newsize >= $pixsize) {
$resize = false;
}
$newimage = true;
if (in_array($file, $this->imagekeys)) {
$newimage = false;
$info = $this->getImageBuffer($file);
if (strpos($file, '__tcpdf_'.$this->file_id.'_imgmask_') === FALSE) {
$oldsize = ($info['w'] * $info['h']);
if ((($oldsize < $newsize) AND ($resize)) OR (($oldsize < $pixsize) AND (!$resize))) {
$newimage = true;
}
}
} elseif (($ismask === false) AND ($imgmask === false) AND (strpos($file, '__tcpdf_'.$this->file_id.'_imgmask_') === FALSE)) {
$tempfile_plain = K_PATH_CACHE.'__tcpdf_'.$this->file_id.'_imgmask_plain_'.$filehash;
$tempfile_alpha = K_PATH_CACHE.'__tcpdf_'.$this->file_id.'_imgmask_alpha_'.$filehash;
if (in_array($tempfile_plain, $this->imagekeys)) {
$info = $this->getImageBuffer($tempfile_plain);
$oldsize = ($info['w'] * $info['h']);
if ((($oldsize < $newsize) AND ($resize)) OR (($oldsize < $pixsize) AND (!$resize))) {
$newimage = true;
} else {
$newimage = false;
$imgmask = $this->Image($tempfile_alpha, $x, $y, $w, $h, 'PNG', '', '', $resize, $dpi, '', true, false);
return $this->Image($tempfile_plain, $x, $y, $w, $h, $type, $link, $align, $resize, $dpi, $palign, false, $imgmask);
}
}
}
if ($newimage) {
$type = strtolower($type);
if ($type == '') {
$type = TCPDF_IMAGES::getImageFileType($file, $imsize);
} elseif ($type == 'jpg') {
$type = 'jpeg';
}
$mqr = TCPDF_STATIC::get_mqr();
TCPDF_STATIC::set_mqr(false);
$mtd = '_parse'.$type;
$gdfunction = 'imagecreatefrom'.$type;
$info = false;
if ((method_exists('TCPDF_IMAGES', $mtd)) AND (!($resize AND (function_exists($gdfunction) OR extension_loaded('imagick'))))) {
$info = TCPDF_IMAGES::$mtd($file);
if (($ismask === false) AND ($imgmask === false) AND (strpos($file, '__tcpdf_'.$this->file_id.'_imgmask_') === FALSE)
AND (($info === 'pngalpha') OR (isset($info['trns']) AND !empty($info['trns'])))) {
return $this->ImagePngAlpha($file, $x, $y, $pixw, $pixh, $w, $h, 'PNG', $link, $align, $resize, $dpi, $palign, $filehash);
}
}
if (($info === false) AND function_exists($gdfunction)) {
try {
$img = $gdfunction($file);
if ($img !== false) {
if ($resize) {
$imgr = imagecreatetruecolor($neww, $newh);
if (($type == 'gif') OR ($type == 'png')) {
$imgr = TCPDF_IMAGES::setGDImageTransparency($imgr, $img);
}
imagecopyresampled($imgr, $img, 0, 0, 0, 0, $neww, $newh, $pixw, $pixh);
$img = $imgr;
}
if (($type == 'gif') OR ($type == 'png')) {
$info = TCPDF_IMAGES::_toPNG($img, TCPDF_STATIC::getObjFilename('img', $this->file_id));
} else {
$info = TCPDF_IMAGES::_toJPEG($img, $this->jpeg_quality, TCPDF_STATIC::getObjFilename('img', $this->file_id));
}
}
} catch(Exception $e) {
$info = false;
}
}
if (($info === false) AND extension_loaded('imagick')) {
try {
$img = new Imagick();
if ($type == 'svg') {
if ($file[0] === '@') {
$svgimg = substr($file, 1);
} else {
$svgimg = TCPDF_STATIC::fileGetContents($file);
}
if ($svgimg !== FALSE) {
$regs = array();
if (preg_match('/<svg([^\>]*)>/si', $svgimg, $regs)) {
$svgtag = $regs[1];
$tmp = array();
if (preg_match('/[\s]+width[\s]*=[\s]*"([^"]*)"/si', $svgtag, $tmp)) {
$ow = $this->getHTMLUnitToUnits($tmp[1], 1, $this->svgunit, false);
$owu = sprintf('%F', ($ow * $dpi / 72)).$this->pdfunit;
$svgtag = preg_replace('/[\s]+width[\s]*=[\s]*"[^"]*"/si', ' width="'.$owu.'"', $svgtag, 1);
} else {
$ow = $w;
}
$tmp = array();
if (preg_match('/[\s]+height[\s]*=[\s]*"([^"]*)"/si', $svgtag, $tmp)) {
$oh = $this->getHTMLUnitToUnits($tmp[1], 1, $this->svgunit, false);
$ohu = sprintf('%F', ($oh * $dpi / 72)).$this->pdfunit;
$svgtag = preg_replace('/[\s]+height[\s]*=[\s]*"[^"]*"/si', ' height="'.$ohu.'"', $svgtag, 1);
} else {
$oh = $h;
}
$tmp = array();
if (!preg_match('/[\s]+viewBox[\s]*=[\s]*"[\s]*([0-9\.]+)[\s]+([0-9\.]+)[\s]+([0-9\.]+)[\s]+([0-9\.]+)[\s]*"/si', $svgtag, $tmp)) {
$vbw = ($ow * $this->imgscale * $this->k);
$vbh = ($oh * $this->imgscale * $this->k);
$vbox = sprintf(' viewBox="0 0 %F %F" ', $vbw, $vbh);
$svgtag = $vbox.$svgtag;
}
$svgimg = preg_replace('/<svg([^\>]*)>/si', '<svg'.$svgtag.'>', $svgimg, 1);
}
$img->readImageBlob($svgimg);
}
} else {
$img->readImage($file);
}
if ($resize) {
$img->resizeImage($neww, $newh, 10, 1, false);
}
$img->setCompressionQuality($this->jpeg_quality);
$img->setImageFormat('jpeg');
$tempname = TCPDF_STATIC::getObjFilename('img', $this->file_id);
$img->writeImage($tempname);
$info = TCPDF_IMAGES::_parsejpeg($tempname);
unlink($tempname);
$img->destroy();
} catch(Exception $e) {
$info = false;
}
}
if ($info === false) {
return;
}
TCPDF_STATIC::set_mqr($mqr);
if ($ismask) {
$info['cs'] = 'DeviceGray';
}
if ($imgmask !== false) {
$info['masked'] = $imgmask;
}
if (!empty($exurl)) {
$info['exurl'] = $exurl;
}
$info['altimgs'] = $altimgs;
$info['i'] = $this->setImageBuffer($file, $info);
}
$this->img_rb_y = $y + $h;
if ($this->rtl) {
if ($palign == 'L') {
$ximg = $this->lMargin;
} elseif ($palign == 'C') {
$ximg = ($this->w + $this->lMargin - $this->rMargin - $w) / 2;
} elseif ($palign == 'R') {
$ximg = $this->w - $this->rMargin - $w;
} else {
$ximg = $x - $w;
}
$this->img_rb_x = $ximg;
} else {
if ($palign == 'L') {
$ximg = $this->lMargin;
} elseif ($palign == 'C') {
$ximg = ($this->w + $this->lMargin - $this->rMargin - $w) / 2;
} elseif ($palign == 'R') {
$ximg = $this->w - $this->rMargin - $w;
} else {
$ximg = $x;
}
$this->img_rb_x = $ximg + $w;
}
if ($ismask OR $hidden) {
return $info['i'];
}
$xkimg = $ximg * $this->k;
if (!$alt) {
$this->_out(sprintf('q %F 0 0 %F %F %F cm /I%u Do Q', ($w * $this->k), ($h * $this->k), $xkimg, (($this->h - ($y + $h)) * $this->k), $info['i']));
}
if (!empty($border)) {
$bx = $this->x;
$by = $this->y;
$this->x = $ximg;
if ($this->rtl) {
$this->x += $w;
}
$this->y = $y;
$this->Cell($w, $h, '', $border, 0, '', 0, '', 0, true);
$this->x = $bx;
$this->y = $by;
}
if ($link) {
$this->Link($ximg, $y, $w, $h, $link, 0);
}
switch($align) {
case 'T': {
$this->y = $y;
$this->x = $this->img_rb_x;
break;
}
case 'M': {
$this->y = $y + round($h/2);
$this->x = $this->img_rb_x;
break;
}
case 'B': {
$this->y = $this->img_rb_y;
$this->x = $this->img_rb_x;
break;
}
case 'N': {
$this->SetY($this->img_rb_y);
break;
}
default:{
break;
}
}
$this->endlinex = $this->img_rb_x;
if ($this->inxobj) {
$this->xobjects[$this->xobjid]['images'][] = $info['i'];
}
return $info['i'];
}
protected function ImagePngAlpha($file, $x, $y, $wpx, $hpx, $w, $h, $type, $link, $align, $resize, $dpi, $palign, $filehash='') {
if (empty($filehash)) {
$filehash = md5($file);
}
$tempfile_plain = K_PATH_CACHE.'__tcpdf_'.$this->file_id.'_imgmask_plain_'.$filehash;
$tempfile_alpha = K_PATH_CACHE.'__tcpdf_'.$this->file_id.'_imgmask_alpha_'.$filehash;
$parsed = false;
$parse_error = '';
if (($parsed === false) AND extension_loaded('imagick')) {
try {
$img = new Imagick();
$img->readImage($file);
$imga = TCPDF_STATIC::objclone($img);
if (method_exists($img, 'setImageAlphaChannel') AND defined('Imagick::ALPHACHANNEL_EXTRACT')) {
$img->setImageAlphaChannel(Imagick::ALPHACHANNEL_EXTRACT);
} else {
$img->separateImageChannel(8);
$img->negateImage(true);
}
$img->setImageFormat('png');
$img->writeImage($tempfile_alpha);
if (method_exists($imga, 'setImageMatte')) {
$imga->setImageMatte(false);
} else {
$imga->separateImageChannel(39);
}
$imga->setImageFormat('png');
$imga->writeImage($tempfile_plain);
$parsed = true;
} catch (Exception $e) {
$parse_error = 'Imagick library error: '.$e->getMessage();
}
}
if (($parsed === false) AND function_exists('imagecreatefrompng')) {
try {
$img = imagecreatefrompng($file);
$imgalpha = imagecreate($wpx, $hpx);
for ($c = 0; $c < 256; ++$c) {
ImageColorAllocate($imgalpha, $c, $c, $c);
}
for ($xpx = 0; $xpx < $wpx; ++$xpx) {
for ($ypx = 0; $ypx < $hpx; ++$ypx) {
$color = imagecolorat($img, $xpx, $ypx);
$alpha = $this->getGDgamma($img, $color);
imagesetpixel($imgalpha, $xpx, $ypx, $alpha);
}
}
imagepng($imgalpha, $tempfile_alpha);
imagedestroy($imgalpha);
$imgplain = imagecreatetruecolor($wpx, $hpx);
imagecopy($imgplain, $img, 0, 0, 0, 0, $wpx, $hpx);
imagepng($imgplain, $tempfile_plain);
imagedestroy($imgplain);
$parsed = true;
} catch (Exception $e) {
$parse_error = 'GD library error: '.$e->getMessage();
}
}
if ($parsed === false) {
if (empty($parse_error)) {
$this->Error('TCPDF requires the Imagick or GD extension to handle PNG images with alpha channel.');
} else {
$this->Error($parse_error);
}
}
$imgmask = $this->Image($tempfile_alpha, $x, $y, $w, $h, 'PNG', '', '', $resize, $dpi, '', true, false);
$this->Image($tempfile_plain, $x, $y, $w, $h, $type, $link, $align, $resize, $dpi, $palign, false, $imgmask);
}
protected function getGDgamma($img, $c) {
if (!isset($this->gdgammacache['#'.$c])) {
$colors = imagecolorsforindex($img, $c);
$this->gdgammacache['#'.$c] = (((127 - $colors['alpha']) / 127) * 255);
$this->gdgammacache['#'.$c] = (pow(($this->gdgammacache['#'.$c] / 255), 2.2) * 255);
if (count($this->gdgammacache) > 8) {
array_shift($this->gdgammacache);
}
}
return $this->gdgammacache['#'.$c];
}
public function Ln($h='', $cell=false) {
if (($this->num_columns > 1) AND ($this->y == $this->columns[$this->current_column]['y']) AND isset($this->columns[$this->current_column]['x']) AND ($this->x == $this->columns[$this->current_column]['x'])) {
return;
}
if ($cell) {
if ($this->rtl) {
$cellpadding = $this->cell_padding['R'];
} else {
$cellpadding = $this->cell_padding['L'];
}
} else {
$cellpadding = 0;
}
if ($this->rtl) {
$this->x = $this->w - $this->rMargin - $cellpadding;
} else {
$this->x = $this->lMargin + $cellpadding;
}
if (is_string($h)) {
$h = $this->lasth;
}
$this->y += $h;
$this->newline = true;
}
public function GetX() {
if ($this->rtl) {
return ($this->w - $this->x);
} else {
return $this->x;
}
}
public function GetAbsX() {
return $this->x;
}
public function GetY() {
return $this->y;
}
public function SetX($x, $rtloff=false) {
$x = floatval($x);
if (!$rtloff AND $this->rtl) {
if ($x >= 0) {
$this->x = $this->w - $x;
} else {
$this->x = abs($x);
}
} else {
if ($x >= 0) {
$this->x = $x;
} else {
$this->x = $this->w + $x;
}
}
if ($this->x < 0) {
$this->x = 0;
}
if ($this->x > $this->w) {
$this->x = $this->w;
}
}
public function SetY($y, $resetx=true, $rtloff=false) {
$y = floatval($y);
if ($resetx) {
if (!$rtloff AND $this->rtl) {
$this->x = $this->w - $this->rMargin;
} else {
$this->x = $this->lMargin;
}
}
if ($y >= 0) {
$this->y = $y;
} else {
$this->y = $this->h + $y;
}
if ($this->y < 0) {
$this->y = 0;
}
if ($this->y > $this->h) {
$this->y = $this->h;
}
}
public function SetXY($x, $y, $rtloff=false) {
$this->SetY($y, false, $rtloff);
$this->SetX($x, $rtloff);
}
public function SetAbsX($x) {
$this->x = floatval($x);
}
public function SetAbsY($y) {
$this->y = floatval($y);
}
public function SetAbsXY($x, $y) {
$this->SetAbsX($x);
$this->SetAbsY($y);
}
public function Output($name='doc.pdf', $dest='I') {
if ($this->state < 3) {
$this->Close();
}
if (is_bool($dest)) {
$dest = $dest ? 'D' : 'F';
}
$dest = strtoupper($dest);
if ($dest[0] != 'F') {
$name = preg_replace('/[\s]+/', '_', $name);
$name = preg_replace('/[^a-zA-Z0-9_\.-]/', '', $name);
}
if ($this->sign) {
$pdfdoc = $this->getBuffer();
$pdfdoc = substr($pdfdoc, 0, -1);
$byterange_string_len = strlen(TCPDF_STATIC::$byterange_string);
$byte_range = array();
$byte_range[0] = 0;
$byte_range[1] = strpos($pdfdoc, TCPDF_STATIC::$byterange_string) + $byterange_string_len + 10;
$byte_range[2] = $byte_range[1] + $this->signature_max_length + 2;
$byte_range[3] = strlen($pdfdoc) - $byte_range[2];
$pdfdoc = substr($pdfdoc, 0, $byte_range[1]).substr($pdfdoc, $byte_range[2]);
$byterange = sprintf('/ByteRange[0 %u %u %u]', $byte_range[1], $byte_range[2], $byte_range[3]);
$byterange .= str_repeat(' ', ($byterange_string_len - strlen($byterange)));
$pdfdoc = str_replace(TCPDF_STATIC::$byterange_string, $byterange, $pdfdoc);
$tempdoc = TCPDF_STATIC::getObjFilename('doc', $this->file_id);
$f = TCPDF_STATIC::fopenLocal($tempdoc, 'wb');
if (!$f) {
$this->Error('Unable to create temporary file: '.$tempdoc);
}
$pdfdoc_length = strlen($pdfdoc);
fwrite($f, $pdfdoc, $pdfdoc_length);
fclose($f);
$tempsign = TCPDF_STATIC::getObjFilename('sig', $this->file_id);
if (empty($this->signature_data['extracerts'])) {
openssl_pkcs7_sign($tempdoc, $tempsign, $this->signature_data['signcert'], array($this->signature_data['privkey'], $this->signature_data['password']), array(), PKCS7_BINARY | PKCS7_DETACHED);
} else {
openssl_pkcs7_sign($tempdoc, $tempsign, $this->signature_data['signcert'], array($this->signature_data['privkey'], $this->signature_data['password']), array(), PKCS7_BINARY | PKCS7_DETACHED, $this->signature_data['extracerts']);
}
$signature = file_get_contents($tempsign);
$signature = substr($signature, $pdfdoc_length);
$signature = substr($signature, (strpos($signature, "%%EOF\n\n------") + 13));
$tmparr = explode("\n\n", $signature);
$signature = $tmparr[1];
$signature = base64_decode(trim($signature));
$signature = $this->applyTSA($signature);
$signature = current(unpack('H*', $signature));
$signature = str_pad($signature, $this->signature_max_length, '0');
$this->buffer = substr($pdfdoc, 0, $byte_range[1]).'<'.$signature.'>'.substr($pdfdoc, $byte_range[1]);
$this->bufferlen = strlen($this->buffer);
}
switch($dest) {
case 'I': {
if (ob_get_contents()) {
$this->Error('Some data has already been output, can\'t send PDF file');
}
if (php_sapi_name() != 'cli') {
header('Content-Type: application/pdf');
if (headers_sent()) {
$this->Error('Some data has already been output to browser, can\'t send PDF file');
}
header('Cache-Control: private, must-revalidate, post-check=0, pre-check=0, max-age=1');
header('Pragma: public');
header('Expires: Sat, 26 Jul 1997 05:00:00 GMT');
header('Last-Modified: '.gmdate('D, d M Y H:i:s').' GMT');
header('Content-Disposition: inline; filename="'.basename($name).'"');
TCPDF_STATIC::sendOutputData($this->getBuffer(), $this->bufferlen);
} else {
echo $this->getBuffer();
}
break;
}
case 'D': {
if (ob_get_contents()) {
$this->Error('Some data has already been output, can\'t send PDF file');
}
header('Content-Description: File Transfer');
if (headers_sent()) {
$this->Error('Some data has already been output to browser, can\'t send PDF file');
}
header('Cache-Control: private, must-revalidate, post-check=0, pre-check=0, max-age=1');
header('Pragma: public');
header('Expires: Sat, 26 Jul 1997 05:00:00 GMT');
header('Last-Modified: '.gmdate('D, d M Y H:i:s').' GMT');
if (strpos(php_sapi_name(), 'cgi') === false) {
header('Content-Type: application/force-download');
header('Content-Type: application/octet-stream', false);
header('Content-Type: application/download', false);
header('Content-Type: application/pdf', false);
} else {
header('Content-Type: application/pdf');
}
header('Content-Disposition: attachment; filename="'.basename($name).'"');
header('Content-Transfer-Encoding: binary');
TCPDF_STATIC::sendOutputData($this->getBuffer(), $this->bufferlen);
break;
}
case 'F':
case 'FI':
case 'FD': {
$f = TCPDF_STATIC::fopenLocal($name, 'wb');
if (!$f) {
$this->Error('Unable to create output file: '.$name);
}
fwrite($f, $this->getBuffer(), $this->bufferlen);
fclose($f);
if ($dest == 'FI') {
header('Content-Type: application/pdf');
header('Cache-Control: private, must-revalidate, post-check=0, pre-check=0, max-age=1');
header('Pragma: public');
header('Expires: Sat, 26 Jul 1997 05:00:00 GMT');
header('Last-Modified: '.gmdate('D, d M Y H:i:s').' GMT');
header('Content-Disposition: inline; filename="'.basename($name).'"');
TCPDF_STATIC::sendOutputData(file_get_contents($name), filesize($name));
} elseif ($dest == 'FD') {
if (ob_get_contents()) {
$this->Error('Some data has already been output, can\'t send PDF file');
}
header('Content-Description: File Transfer');
if (headers_sent()) {
$this->Error('Some data has already been output to browser, can\'t send PDF file');
}
header('Cache-Control: private, must-revalidate, post-check=0, pre-check=0, max-age=1');
header('Pragma: public');
header('Expires: Sat, 26 Jul 1997 05:00:00 GMT');
header('Last-Modified: '.gmdate('D, d M Y H:i:s').' GMT');
if (strpos(php_sapi_name(), 'cgi') === false) {
header('Content-Type: application/force-download');
header('Content-Type: application/octet-stream', false);
header('Content-Type: application/download', false);
header('Content-Type: application/pdf', false);
} else {
header('Content-Type: application/pdf');
}
header('Content-Disposition: attachment; filename="'.basename($name).'"');
header('Content-Transfer-Encoding: binary');
TCPDF_STATIC::sendOutputData(file_get_contents($name), filesize($name));
}
break;
}
case 'E': {
$retval = 'Content-Type: application/pdf;'."\r\n";
$retval .= ' name="'.$name.'"'."\r\n";
$retval .= 'Content-Transfer-Encoding: base64'."\r\n";
$retval .= 'Content-Disposition: attachment;'."\r\n";
$retval .= ' filename="'.$name.'"'."\r\n\r\n";
$retval .= chunk_split(base64_encode($this->getBuffer()), 76, "\r\n");
return $retval;
}
case 'S': {
return $this->getBuffer();
}
default: {
$this->Error('Incorrect output destination: '.$dest);
}
}
return '';
}
public function _destroy($destroyall=false, $preserve_objcopy=false) {
if ($destroyall AND !$preserve_objcopy) {
$tmpfiles = glob(K_PATH_CACHE.'__tcpdf_'.$this->file_id.'_*');
if (!empty($tmpfiles)) {
array_map('unlink', $tmpfiles);
}
}
$preserve = array(
'file_id',
'internal_encoding',
'state',
'bufferlen',
'buffer',
'cached_files',
'sign',
'signature_data',
'signature_max_length',
'byterange_string',
'tsa_timestamp',
'tsa_data'
);
foreach (array_keys(get_object_vars($this)) as $val) {
if ($destroyall OR !in_array($val, $preserve)) {
if ((!$preserve_objcopy OR ($val != 'objcopy')) AND ($val != 'file_id') AND isset($this->$val)) {
unset($this->$val);
}
}
}
}
protected function _dochecks() {
if (1.1 == 1) {
$this->Error('Don\'t alter the locale before including class file');
}
if (sprintf('%.1F', 1.0) != '1.0') {
setlocale(LC_NUMERIC, 'C');
}
}
protected function getInternalPageNumberAliases($a= '') {
$alias = array();
$alias = array('u' => array(), 'a' => array());
$u = '{'.$a.'}';
$alias['u'][] = TCPDF_STATIC::_escape($u);
if ($this->isunicode) {
$alias['u'][] = TCPDF_STATIC::_escape(TCPDF_FONTS::UTF8ToLatin1($u, $this->isunicode, $this->CurrentFont));
$alias['u'][] = TCPDF_STATIC::_escape(TCPDF_FONTS::utf8StrRev($u, false, $this->tmprtl, $this->isunicode, $this->CurrentFont));
$alias['a'][] = TCPDF_STATIC::_escape(TCPDF_FONTS::UTF8ToLatin1($a, $this->isunicode, $this->CurrentFont));
$alias['a'][] = TCPDF_STATIC::_escape(TCPDF_FONTS::utf8StrRev($a, false, $this->tmprtl, $this->isunicode, $this->CurrentFont));
}
$alias['a'][] = TCPDF_STATIC::_escape($a);
return $alias;
}
protected function getAllInternalPageNumberAliases() {
$basic_alias = array(TCPDF_STATIC::$alias_tot_pages, TCPDF_STATIC::$alias_num_page, TCPDF_STATIC::$alias_group_tot_pages, TCPDF_STATIC::$alias_group_num_page, TCPDF_STATIC::$alias_right_shift);
$pnalias = array();
foreach($basic_alias as $k => $a) {
$pnalias[$k] = $this->getInternalPageNumberAliases($a);
}
return $pnalias;
}
protected function replaceRightShiftPageNumAliases($page, $aliases, $diff) {
foreach ($aliases as $type => $alias) {
foreach ($alias as $a) {
$startnum = (strpos($a, ':') + 1);
$a = substr($a, 0, $startnum);
if (($pos = strpos($page, $a)) !== false) {
$endnum = strpos($page, '}', $pos);
$aa = substr($page, $pos, ($endnum - $pos + 1));
$ratio = substr($page, ($pos + $startnum), ($endnum - $pos - $startnum));
$ratio = preg_replace('/[^0-9\.]/', '', $ratio);
$ratio = floatval($ratio);
if ($type == 'u') {
$chrdiff = floor(($diff + 12) * $ratio);
$shift = str_repeat(' ', $chrdiff);
$shift = TCPDF_FONTS::UTF8ToUTF16BE($shift, false, $this->isunicode, $this->CurrentFont);
} else {
$chrdiff = floor(($diff + 11) * $ratio);
$shift = str_repeat(' ', $chrdiff);
}
$page = str_replace($aa, $shift, $page);
}
}
}
return $page;
}
protected function setPageBoxTypes($boxes) {
$this->page_boxes = array();
foreach ($boxes as $box) {
if (in_array($box, TCPDF_STATIC::$pageboxes)) {
$this->page_boxes[] = $box;
}
}
}
protected function _putpages() {
$filter = ($this->compress) ? '/Filter /FlateDecode ' : '';
$pnalias = $this->getAllInternalPageNumberAliases();
$num_pages = $this->numpages;
$ptpa = TCPDF_STATIC::formatPageNumber(($this->starting_page_number + $num_pages - 1));
$ptpu = TCPDF_FONTS::UTF8ToUTF16BE($ptpa, false, $this->isunicode, $this->CurrentFont);
$ptp_num_chars = $this->GetNumChars($ptpa);
$pagegroupnum = 0;
$groupnum = 0;
$ptgu = 1;
$ptga = 1;
$ptg_num_chars = 1;
for ($n = 1; $n <= $num_pages; ++$n) {
$temppage = $this->getPageBuffer($n);
$pagelen = strlen($temppage);
$pnpa = TCPDF_STATIC::formatPageNumber(($this->starting_page_number + $n - 1));
$pnpu = TCPDF_FONTS::UTF8ToUTF16BE($pnpa, false, $this->isunicode, $this->CurrentFont);
$pnp_num_chars = $this->GetNumChars($pnpa);
$pdiff = 0;
$gdiff = 0;
if (!empty($this->pagegroups)) {
if (isset($this->newpagegroup[$n])) {
$pagegroupnum = 0;
++$groupnum;
$ptga = TCPDF_STATIC::formatPageNumber($this->pagegroups[$groupnum]);
$ptgu = TCPDF_FONTS::UTF8ToUTF16BE($ptga, false, $this->isunicode, $this->CurrentFont);
$ptg_num_chars = $this->GetNumChars($ptga);
}
++$pagegroupnum;
$pnga = TCPDF_STATIC::formatPageNumber($pagegroupnum);
$pngu = TCPDF_FONTS::UTF8ToUTF16BE($pnga, false, $this->isunicode, $this->CurrentFont);
$png_num_chars = $this->GetNumChars($pnga);
$replace = array();
$replace[] = array($ptgu, $ptg_num_chars, 9, $pnalias[2]['u']);
$replace[] = array($ptga, $ptg_num_chars, 7, $pnalias[2]['a']);
$replace[] = array($pngu, $png_num_chars, 9, $pnalias[3]['u']);
$replace[] = array($pnga, $png_num_chars, 7, $pnalias[3]['a']);
list($temppage, $gdiff) = TCPDF_STATIC::replacePageNumAliases($temppage, $replace, $gdiff);
}
$replace = array();
$replace[] = array($ptpu, $ptp_num_chars, 9, $pnalias[0]['u']);
$replace[] = array($ptpa, $ptp_num_chars, 7, $pnalias[0]['a']);
$replace[] = array($pnpu, $pnp_num_chars, 9, $pnalias[1]['u']);
$replace[] = array($pnpa, $pnp_num_chars, 7, $pnalias[1]['a']);
list($temppage, $pdiff) = TCPDF_STATIC::replacePageNumAliases($temppage, $replace, $pdiff);
$temppage = $this->replaceRightShiftPageNumAliases($temppage, $pnalias[4], max($pdiff, $gdiff));
$temppage = str_replace($this->epsmarker, '', $temppage);
$this->page_obj_id[$n] = $this->_newobj();
$out = '<<';
$out .= ' /Type /Page';
$out .= ' /Parent 1 0 R';
if (empty($this->signature_data['approval']) OR ($this->signature_data['approval'] != 'A')) {
$out .= ' /LastModified '.$this->_datestring(0, $this->doc_modification_timestamp);
}
$out .= ' /Resources 2 0 R';
foreach ($this->page_boxes as $box) {
$out .= ' /'.$box;
$out .= sprintf(' [%F %F %F %F]', $this->pagedim[$n][$box]['llx'], $this->pagedim[$n][$box]['lly'], $this->pagedim[$n][$box]['urx'], $this->pagedim[$n][$box]['ury']);
}
if (isset($this->pagedim[$n]['BoxColorInfo']) AND !empty($this->pagedim[$n]['BoxColorInfo'])) {
$out .= ' /BoxColorInfo <<';
foreach ($this->page_boxes as $box) {
if (isset($this->pagedim[$n]['BoxColorInfo'][$box])) {
$out .= ' /'.$box.' <<';
if (isset($this->pagedim[$n]['BoxColorInfo'][$box]['C'])) {
$color = $this->pagedim[$n]['BoxColorInfo'][$box]['C'];
$out .= ' /C [';
$out .= sprintf(' %F %F %F', ($color[0] / 255), ($color[1] / 255), ($color[2] / 255));
$out .= ' ]';
}
if (isset($this->pagedim[$n]['BoxColorInfo'][$box]['W'])) {
$out .= ' /W '.($this->pagedim[$n]['BoxColorInfo'][$box]['W'] * $this->k);
}
if (isset($this->pagedim[$n]['BoxColorInfo'][$box]['S'])) {
$out .= ' /S /'.$this->pagedim[$n]['BoxColorInfo'][$box]['S'];
}
if (isset($this->pagedim[$n]['BoxColorInfo'][$box]['D'])) {
$dashes = $this->pagedim[$n]['BoxColorInfo'][$box]['D'];
$out .= ' /D [';
foreach ($dashes as $dash) {
$out .= sprintf(' %F', ($dash * $this->k));
}
$out .= ' ]';
}
$out .= ' >>';
}
}
$out .= ' >>';
}
$out .= ' /Contents '.($this->n + 1).' 0 R';
$out .= ' /Rotate '.$this->pagedim[$n]['Rotate'];
if (!$this->pdfa_mode) {
$out .= ' /Group << /Type /Group /S /Transparency /CS /DeviceRGB >>';
}
if (isset($this->pagedim[$n]['trans']) AND !empty($this->pagedim[$n]['trans'])) {
if (isset($this->pagedim[$n]['trans']['Dur'])) {
$out .= ' /Dur '.$this->pagedim[$n]['trans']['Dur'];
}
$out .= ' /Trans <<';
$out .= ' /Type /Trans';
if (isset($this->pagedim[$n]['trans']['S'])) {
$out .= ' /S /'.$this->pagedim[$n]['trans']['S'];
}
if (isset($this->pagedim[$n]['trans']['D'])) {
$out .= ' /D '.$this->pagedim[$n]['trans']['D'];
}
if (isset($this->pagedim[$n]['trans']['Dm'])) {
$out .= ' /Dm /'.$this->pagedim[$n]['trans']['Dm'];
}
if (isset($this->pagedim[$n]['trans']['M'])) {
$out .= ' /M /'.$this->pagedim[$n]['trans']['M'];
}
if (isset($this->pagedim[$n]['trans']['Di'])) {
$out .= ' /Di '.$this->pagedim[$n]['trans']['Di'];
}
if (isset($this->pagedim[$n]['trans']['SS'])) {
$out .= ' /SS '.$this->pagedim[$n]['trans']['SS'];
}
if (isset($this->pagedim[$n]['trans']['B'])) {
$out .= ' /B '.$this->pagedim[$n]['trans']['B'];
}
$out .= ' >>';
}
$out .= $this->_getannotsrefs($n);
$out .= ' /PZ '.$this->pagedim[$n]['PZ'];
$out .= ' >>';
$out .= "\n".'endobj';
$this->_out($out);
$p = ($this->compress) ? gzcompress($temppage) : $temppage;
$this->_newobj();
$p = $this->_getrawstream($p);
$this->_out('<<'.$filter.'/Length '.strlen($p).'>> stream'."\n".$p."\n".'endstream'."\n".'endobj');
}
$out = $this->_getobj(1)."\n";
$out .= '<< /Type /Pages /Kids [';
foreach($this->page_obj_id as $page_obj) {
$out .= ' '.$page_obj.' 0 R';
}
$out .= ' ] /Count '.$num_pages.' >>';
$out .= "\n".'endobj';
$this->_out($out);
}
protected function _getannotsrefs($n) {
if (!(isset($this->PageAnnots[$n]) OR ($this->sign AND isset($this->signature_data['cert_type'])))) {
return '';
}
$out = ' /Annots [';
if (isset($this->PageAnnots[$n])) {
foreach ($this->PageAnnots[$n] as $key => $val) {
if (!in_array($val['n'], $this->radio_groups)) {
$out .= ' '.$val['n'].' 0 R';
}
}
if (isset($this->radiobutton_groups[$n])) {
foreach ($this->radiobutton_groups[$n] as $key => $data) {
if (isset($data['n'])) {
$out .= ' '.$data['n'].' 0 R';
}
}
}
}
if ($this->sign AND ($n == $this->signature_appearance['page']) AND isset($this->signature_data['cert_type'])) {
$out .= ' '.$this->sig_obj_id.' 0 R';
}
if (!empty($this->empty_signature_appearance)) {
foreach ($this->empty_signature_appearance as $esa) {
if ($esa['page'] == $n) {
$out .= ' '.$esa['objid'].' 0 R';
}
}
}
$out .= ' ]';
return $out;
}
protected function _putannotsobjs() {
for ($n=1; $n <= $this->numpages; ++$n) {
if (isset($this->PageAnnots[$n])) {
foreach ($this->PageAnnots[$n] as $key => $pl) {
$annot_obj_id = $this->PageAnnots[$n][$key]['n'];
if (isset($this->radiobutton_groups[$n][$pl['txt']]) AND is_array($this->radiobutton_groups[$n][$pl['txt']])) {
$radio_button_obj_id = $this->radiobutton_groups[$n][$pl['txt']]['n'];
$annots = '<<';
$annots .= ' /Type /Annot';
$annots .= ' /Subtype /Widget';
$annots .= ' /Rect [0 0 0 0]';
if ($this->radiobutton_groups[$n][$pl['txt']]['#readonly#']) {
$annots .= ' /F 68';
$annots .= ' /Ff 49153';
} else {
$annots .= ' /F 4';
$annots .= ' /Ff 49152';
}
$annots .= ' /T '.$this->_datastring($pl['txt'], $radio_button_obj_id);
if (isset($pl['opt']['tu']) AND is_string($pl['opt']['tu'])) {
$annots .= ' /TU '.$this->_datastring($pl['opt']['tu'], $radio_button_obj_id);
}
$annots .= ' /FT /Btn';
$annots .= ' /Kids [';
$defval = '';
foreach ($this->radiobutton_groups[$n][$pl['txt']] as $key => $data) {
if (isset($data['kid'])) {
$annots .= ' '.$data['kid'].' 0 R';
if ($data['def'] !== 'Off') {
$defval = $data['def'];
}
}
}
$annots .= ' ]';
if (!empty($defval)) {
$annots .= ' /V /'.$defval;
}
$annots .= ' >>';
$this->_out($this->_getobj($radio_button_obj_id)."\n".$annots."\n".'endobj');
$this->form_obj_id[] = $radio_button_obj_id;
$this->radiobutton_groups[$n][$pl['txt']] = $radio_button_obj_id;
}
$formfield = false;
$pl['opt'] = array_change_key_case($pl['opt'], CASE_LOWER);
$a = $pl['x'] * $this->k;
$b = $this->pagedim[$n]['h'] - (($pl['y'] + $pl['h']) * $this->k);
$c = $pl['w'] * $this->k;
$d = $pl['h'] * $this->k;
$rect = sprintf('%F %F %F %F', $a, $b, $a+$c, $b+$d);
$annots = '<</Type /Annot';
$annots .= ' /Subtype /'.$pl['opt']['subtype'];
$annots .= ' /Rect ['.$rect.']';
$ft = array('Btn', 'Tx', 'Ch', 'Sig');
if (isset($pl['opt']['ft']) AND in_array($pl['opt']['ft'], $ft)) {
$annots .= ' /FT /'.$pl['opt']['ft'];
$formfield = true;
}
if ($pl['opt']['subtype'] !== 'Link') {
$annots .= ' /Contents '.$this->_textstring($pl['txt'], $annot_obj_id);
}
$annots .= ' /P '.$this->page_obj_id[$n].' 0 R';
$annots .= ' /NM '.$this->_datastring(sprintf('%04u-%04u', $n, $key), $annot_obj_id);
$annots .= ' /M '.$this->_datestring($annot_obj_id, $this->doc_modification_timestamp);
if (isset($pl['opt']['f'])) {
$fval = 0;
if (is_array($pl['opt']['f'])) {
foreach ($pl['opt']['f'] as $f) {
switch (strtolower($f)) {
case 'invisible': {
$fval += 1 << 0;
break;
}
case 'hidden': {
$fval += 1 << 1;
break;
}
case 'print': {
$fval += 1 << 2;
break;
}
case 'nozoom': {
$fval += 1 << 3;
break;
}
case 'norotate': {
$fval += 1 << 4;
break;
}
case 'noview': {
$fval += 1 << 5;
break;
}
case 'readonly': {
$fval += 1 << 6;
break;
}
case 'locked': {
$fval += 1 << 8;
break;
}
case 'togglenoview': {
$fval += 1 << 9;
break;
}
case 'lockedcontents': {
$fval += 1 << 10;
break;
}
default: {
break;
}
}
}
} else {
$fval = intval($pl['opt']['f']);
}
} else {
$fval = 4;
}
if ($this->pdfa_mode) {
$fval |= 4;
}
$annots .= ' /F '.intval($fval);
if (isset($pl['opt']['as']) AND is_string($pl['opt']['as'])) {
$annots .= ' /AS /'.$pl['opt']['as'];
}
if (isset($pl['opt']['ap'])) {
$annots .= ' /AP <<';
if (is_array($pl['opt']['ap'])) {
foreach ($pl['opt']['ap'] as $apmode => $apdef) {
$annots .= ' /'.strtoupper($apmode);
if (is_array($apdef)) {
$annots .= ' <<';
foreach ($apdef as $apstate => $stream) {
$apsobjid = $this->_putAPXObject($c, $d, $stream);
$annots .= ' /'.$apstate.' '.$apsobjid.' 0 R';
}
$annots .= ' >>';
} else {
$apsobjid = $this->_putAPXObject($c, $d, $apdef);
$annots .= ' '.$apsobjid.' 0 R';
}
}
} else {
$annots .= $pl['opt']['ap'];
}
$annots .= ' >>';
}
if (isset($pl['opt']['bs']) AND (is_array($pl['opt']['bs']))) {
$annots .= ' /BS <<';
$annots .= ' /Type /Border';
if (isset($pl['opt']['bs']['w'])) {
$annots .= ' /W '.intval($pl['opt']['bs']['w']);
}
$bstyles = array('S', 'D', 'B', 'I', 'U');
if (isset($pl['opt']['bs']['s']) AND in_array($pl['opt']['bs']['s'], $bstyles)) {
$annots .= ' /S /'.$pl['opt']['bs']['s'];
}
if (isset($pl['opt']['bs']['d']) AND (is_array($pl['opt']['bs']['d']))) {
$annots .= ' /D [';
foreach ($pl['opt']['bs']['d'] as $cord) {
$annots .= ' '.intval($cord);
}
$annots .= ']';
}
$annots .= ' >>';
} else {
$annots .= ' /Border [';
if (isset($pl['opt']['border']) AND (count($pl['opt']['border']) >= 3)) {
$annots .= intval($pl['opt']['border'][0]).' ';
$annots .= intval($pl['opt']['border'][1]).' ';
$annots .= intval($pl['opt']['border'][2]);
if (isset($pl['opt']['border'][3]) AND is_array($pl['opt']['border'][3])) {
$annots .= ' [';
foreach ($pl['opt']['border'][3] as $dash) {
$annots .= intval($dash).' ';
}
$annots .= ']';
}
} else {
$annots .= '0 0 0';
}
$annots .= ']';
}
if (isset($pl['opt']['be']) AND (is_array($pl['opt']['be']))) {
$annots .= ' /BE <<';
$bstyles = array('S', 'C');
if (isset($pl['opt']['be']['s']) AND in_array($pl['opt']['be']['s'], $bstyles)) {
$annots .= ' /S /'.$pl['opt']['bs']['s'];
} else {
$annots .= ' /S /S';
}
if (isset($pl['opt']['be']['i']) AND ($pl['opt']['be']['i'] >= 0) AND ($pl['opt']['be']['i'] <= 2)) {
$annots .= ' /I '.sprintf(' %F', $pl['opt']['be']['i']);
}
$annots .= '>>';
}
if (isset($pl['opt']['c']) AND (is_array($pl['opt']['c'])) AND !empty($pl['opt']['c'])) {
$annots .= ' /C '.TCPDF_COLORS::getColorStringFromArray($pl['opt']['c']);
}
$markups = array('text', 'freetext', 'line', 'square', 'circle', 'polygon', 'polyline', 'highlight', 'underline', 'squiggly', 'strikeout', 'stamp', 'caret', 'ink', 'fileattachment', 'sound');
if (in_array(strtolower($pl['opt']['subtype']), $markups)) {
if (isset($pl['opt']['t']) AND is_string($pl['opt']['t'])) {
$annots .= ' /T '.$this->_textstring($pl['opt']['t'], $annot_obj_id);
}
if (isset($pl['opt']['ca'])) {
$annots .= ' /CA '.sprintf('%F', floatval($pl['opt']['ca']));
}
if (isset($pl['opt']['rc'])) {
$annots .= ' /RC '.$this->_textstring($pl['opt']['rc'], $annot_obj_id);
}
$annots .= ' /CreationDate '.$this->_datestring($annot_obj_id, $this->doc_creation_timestamp);
if (isset($pl['opt']['subj'])) {
$annots .= ' /Subj '.$this->_textstring($pl['opt']['subj'], $annot_obj_id);
}
}
$lineendings = array('Square', 'Circle', 'Diamond', 'OpenArrow', 'ClosedArrow', 'None', 'Butt', 'ROpenArrow', 'RClosedArrow', 'Slash');
switch (strtolower($pl['opt']['subtype'])) {
case 'text': {
if (isset($pl['opt']['open'])) {
$annots .= ' /Open '. (strtolower($pl['opt']['open']) == 'true' ? 'true' : 'false');
}
$iconsapp = array('Comment', 'Help', 'Insert', 'Key', 'NewParagraph', 'Note', 'Paragraph');
if (isset($pl['opt']['name']) AND in_array($pl['opt']['name'], $iconsapp)) {
$annots .= ' /Name /'.$pl['opt']['name'];
} else {
$annots .= ' /Name /Note';
}
$statemodels = array('Marked', 'Review');
if (isset($pl['opt']['statemodel']) AND in_array($pl['opt']['statemodel'], $statemodels)) {
$annots .= ' /StateModel /'.$pl['opt']['statemodel'];
} else {
$pl['opt']['statemodel'] = 'Marked';
$annots .= ' /StateModel /'.$pl['opt']['statemodel'];
}
if ($pl['opt']['statemodel'] == 'Marked') {
$states = array('Accepted', 'Unmarked');
} else {
$states = array('Accepted', 'Rejected', 'Cancelled', 'Completed', 'None');
}
if (isset($pl['opt']['state']) AND in_array($pl['opt']['state'], $states)) {
$annots .= ' /State /'.$pl['opt']['state'];
} else {
if ($pl['opt']['statemodel'] == 'Marked') {
$annots .= ' /State /Unmarked';
} else {
$annots .= ' /State /None';
}
}
break;
}
case 'link': {
if (is_string($pl['txt']) && !empty($pl['txt'])) {
if ($pl['txt'][0] == '#') {
$annots .= ' /Dest /'.TCPDF_STATIC::encodeNameObject(substr($pl['txt'], 1));
} elseif ($pl['txt'][0] == '%') {
$filename = basename(substr($pl['txt'], 1));
$annots .= ' /A << /S /GoToE /D [0 /Fit] /NewWindow true /T << /R /C /P '.($n - 1).' /A '.$this->embeddedfiles[$filename]['a'].' >> >>';
} elseif ($pl['txt'][0] == '*') {
$filename = basename(substr($pl['txt'], 1));
$jsa = 'var D=event.target.doc;var MyData=D.dataObjects;for (var i in MyData) if (MyData[i].path=="'.$filename.'") D.exportDataObject( { cName : MyData[i].name, nLaunch : 2});';
$annots .= ' /A << /S /JavaScript /JS '.$this->_textstring($jsa, $annot_obj_id).'>>';
} else {
$parsedUrl = parse_url($pl['txt']);
if (empty($parsedUrl['scheme']) AND (strtolower(substr($parsedUrl['path'], -4)) == '.pdf')) {
$dest = '[0 /Fit]';
if (!empty($parsedUrl['fragment'])) {
$tmp = explode('=', $parsedUrl['fragment']);
$dest = '('.((count($tmp) == 2) ? $tmp[1] : $tmp[0]).')';
}
$annots .= ' /A <</S /GoToR /D '.$dest.' /F '.$this->_datastring($this->unhtmlentities($parsedUrl['path']), $annot_obj_id).' /NewWindow true>>';
} else {
$annots .= ' /A <</S /URI /URI '.$this->_datastring($this->unhtmlentities($pl['txt']), $annot_obj_id).'>>';
}
}
} elseif (isset($this->links[$pl['txt']])) {
$l = $this->links[$pl['txt']];
if (isset($this->page_obj_id[($l['p'])])) {
$annots .= sprintf(' /Dest [%u 0 R /XYZ 0 %F null]', $this->page_obj_id[($l['p'])], ($this->pagedim[$l['p']]['h'] - ($l['y'] * $this->k)));
}
}
$hmodes = array('N', 'I', 'O', 'P');
if (isset($pl['opt']['h']) AND in_array($pl['opt']['h'], $hmodes)) {
$annots .= ' /H /'.$pl['opt']['h'];
} else {
$annots .= ' /H /I';
}
break;
}
case 'freetext': {
if (isset($pl['opt']['da']) AND !empty($pl['opt']['da'])) {
$annots .= ' /DA ('.$pl['opt']['da'].')';
}
if (isset($pl['opt']['q']) AND ($pl['opt']['q'] >= 0) AND ($pl['opt']['q'] <= 2)) {
$annots .= ' /Q '.intval($pl['opt']['q']);
}
if (isset($pl['opt']['rc'])) {
$annots .= ' /RC '.$this->_textstring($pl['opt']['rc'], $annot_obj_id);
}
if (isset($pl['opt']['ds'])) {
$annots .= ' /DS '.$this->_textstring($pl['opt']['ds'], $annot_obj_id);
}
if (isset($pl['opt']['cl']) AND is_array($pl['opt']['cl'])) {
$annots .= ' /CL [';
foreach ($pl['opt']['cl'] as $cl) {
$annots .= sprintf('%F ', $cl * $this->k);
}
$annots .= ']';
}
$tfit = array('FreeText', 'FreeTextCallout', 'FreeTextTypeWriter');
if (isset($pl['opt']['it']) AND in_array($pl['opt']['it'], $tfit)) {
$annots .= ' /IT /'.$pl['opt']['it'];
}
if (isset($pl['opt']['rd']) AND is_array($pl['opt']['rd'])) {
$l = $pl['opt']['rd'][0] * $this->k;
$r = $pl['opt']['rd'][1] * $this->k;
$t = $pl['opt']['rd'][2] * $this->k;
$b = $pl['opt']['rd'][3] * $this->k;
$annots .= ' /RD ['.sprintf('%F %F %F %F', $l, $r, $t, $b).']';
}
if (isset($pl['opt']['le']) AND in_array($pl['opt']['le'], $lineendings)) {
$annots .= ' /LE /'.$pl['opt']['le'];
}
break;
}
case 'line': {
break;
}
case 'square': {
break;
}
case 'circle': {
break;
}
case 'polygon': {
break;
}
case 'polyline': {
break;
}
case 'highlight': {
break;
}
case 'underline': {
break;
}
case 'squiggly': {
break;
}
case 'strikeout': {
break;
}
case 'stamp': {
break;
}
case 'caret': {
break;
}
case 'ink': {
break;
}
case 'popup': {
break;
}
case 'fileattachment': {
if ($this->pdfa_mode) {
break;
}
if (!isset($pl['opt']['fs'])) {
break;
}
$filename = basename($pl['opt']['fs']);
if (isset($this->embeddedfiles[$filename]['f'])) {
$annots .= ' /FS '.$this->embeddedfiles[$filename]['f'].' 0 R';
$iconsapp = array('Graph', 'Paperclip', 'PushPin', 'Tag');
if (isset($pl['opt']['name']) AND in_array($pl['opt']['name'], $iconsapp)) {
$annots .= ' /Name /'.$pl['opt']['name'];
} else {
$annots .= ' /Name /PushPin';
}
$this->embeddedfiles[$filename]['a'] = $key;
}
break;
}
case 'sound': {
if (!isset($pl['opt']['fs'])) {
break;
}
$filename = basename($pl['opt']['fs']);
if (isset($this->embeddedfiles[$filename]['f'])) {
$annots .= ' /Sound '.$this->embeddedfiles[$filename]['f'].' 0 R';
$iconsapp = array('Speaker', 'Mic');
if (isset($pl['opt']['name']) AND in_array($pl['opt']['name'], $iconsapp)) {
$annots .= ' /Name /'.$pl['opt']['name'];
} else {
$annots .= ' /Name /Speaker';
}
}
break;
}
case 'movie': {
break;
}
case 'widget': {
$hmode = array('N', 'I', 'O', 'P', 'T');
if (isset($pl['opt']['h']) AND in_array($pl['opt']['h'], $hmode)) {
$annots .= ' /H /'.$pl['opt']['h'];
}
if (isset($pl['opt']['mk']) AND (is_array($pl['opt']['mk'])) AND !empty($pl['opt']['mk'])) {
$annots .= ' /MK <<';
if (isset($pl['opt']['mk']['r'])) {
$annots .= ' /R '.$pl['opt']['mk']['r'];
}
if (isset($pl['opt']['mk']['bc']) AND (is_array($pl['opt']['mk']['bc']))) {
$annots .= ' /BC '.TCPDF_COLORS::getColorStringFromArray($pl['opt']['mk']['bc']);
}
if (isset($pl['opt']['mk']['bg']) AND (is_array($pl['opt']['mk']['bg']))) {
$annots .= ' /BG '.TCPDF_COLORS::getColorStringFromArray($pl['opt']['mk']['bg']);
}
if (isset($pl['opt']['mk']['ca'])) {
$annots .= ' /CA '.$pl['opt']['mk']['ca'];
}
if (isset($pl['opt']['mk']['rc'])) {
$annots .= ' /RC '.$pl['opt']['mk']['rc'];
}
if (isset($pl['opt']['mk']['ac'])) {
$annots .= ' /AC '.$pl['opt']['mk']['ac'];
}
if (isset($pl['opt']['mk']['i'])) {
$info = $this->getImageBuffer($pl['opt']['mk']['i']);
if ($info !== false) {
$annots .= ' /I '.$info['n'].' 0 R';
}
}
if (isset($pl['opt']['mk']['ri'])) {
$info = $this->getImageBuffer($pl['opt']['mk']['ri']);
if ($info !== false) {
$annots .= ' /RI '.$info['n'].' 0 R';
}
}
if (isset($pl['opt']['mk']['ix'])) {
$info = $this->getImageBuffer($pl['opt']['mk']['ix']);
if ($info !== false) {
$annots .= ' /IX '.$info['n'].' 0 R';
}
}
if (isset($pl['opt']['mk']['if']) AND (is_array($pl['opt']['mk']['if'])) AND !empty($pl['opt']['mk']['if'])) {
$annots .= ' /IF <<';
$if_sw = array('A', 'B', 'S', 'N');
if (isset($pl['opt']['mk']['if']['sw']) AND in_array($pl['opt']['mk']['if']['sw'], $if_sw)) {
$annots .= ' /SW /'.$pl['opt']['mk']['if']['sw'];
}
$if_s = array('A', 'P');
if (isset($pl['opt']['mk']['if']['s']) AND in_array($pl['opt']['mk']['if']['s'], $if_s)) {
$annots .= ' /S /'.$pl['opt']['mk']['if']['s'];
}
if (isset($pl['opt']['mk']['if']['a']) AND (is_array($pl['opt']['mk']['if']['a'])) AND !empty($pl['opt']['mk']['if']['a'])) {
$annots .= sprintf(' /A [%F %F]', $pl['opt']['mk']['if']['a'][0], $pl['opt']['mk']['if']['a'][1]);
}
if (isset($pl['opt']['mk']['if']['fb']) AND ($pl['opt']['mk']['if']['fb'])) {
$annots .= ' /FB true';
}
$annots .= '>>';
}
if (isset($pl['opt']['mk']['tp']) AND ($pl['opt']['mk']['tp'] >= 0) AND ($pl['opt']['mk']['tp'] <= 6)) {
$annots .= ' /TP '.intval($pl['opt']['mk']['tp']);
}
$annots .= '>>';
}
if (isset($this->radiobutton_groups[$n][$pl['txt']])) {
$annots .= ' /Parent '.$this->radiobutton_groups[$n][$pl['txt']].' 0 R';
}
if (isset($pl['opt']['t']) AND is_string($pl['opt']['t'])) {
$annots .= ' /T '.$this->_datastring($pl['opt']['t'], $annot_obj_id);
}
if (isset($pl['opt']['tu']) AND is_string($pl['opt']['tu'])) {
$annots .= ' /TU '.$this->_datastring($pl['opt']['tu'], $annot_obj_id);
}
if (isset($pl['opt']['tm']) AND is_string($pl['opt']['tm'])) {
$annots .= ' /TM '.$this->_datastring($pl['opt']['tm'], $annot_obj_id);
}
if (isset($pl['opt']['ff'])) {
if (is_array($pl['opt']['ff'])) {
$flag = 0;
foreach($pl['opt']['ff'] as $val) {
$flag += 1 << ($val - 1);
}
} else {
$flag = intval($pl['opt']['ff']);
}
$annots .= ' /Ff '.$flag;
}
if (isset($pl['opt']['maxlen'])) {
$annots .= ' /MaxLen '.intval($pl['opt']['maxlen']);
}
if (isset($pl['opt']['v'])) {
$annots .= ' /V';
if (is_array($pl['opt']['v'])) {
foreach ($pl['opt']['v'] AS $optval) {
if (is_float($optval)) {
$optval = sprintf('%F', $optval);
}
$annots .= ' '.$optval;
}
} else {
$annots .= ' '.$this->_textstring($pl['opt']['v'], $annot_obj_id);
}
}
if (isset($pl['opt']['dv'])) {
$annots .= ' /DV';
if (is_array($pl['opt']['dv'])) {
foreach ($pl['opt']['dv'] AS $optval) {
if (is_float($optval)) {
$optval = sprintf('%F', $optval);
}
$annots .= ' '.$optval;
}
} else {
$annots .= ' '.$this->_textstring($pl['opt']['dv'], $annot_obj_id);
}
}
if (isset($pl['opt']['rv'])) {
$annots .= ' /RV';
if (is_array($pl['opt']['rv'])) {
foreach ($pl['opt']['rv'] AS $optval) {
if (is_float($optval)) {
$optval = sprintf('%F', $optval);
}
$annots .= ' '.$optval;
}
} else {
$annots .= ' '.$this->_textstring($pl['opt']['rv'], $annot_obj_id);
}
}
if (isset($pl['opt']['a']) AND !empty($pl['opt']['a'])) {
$annots .= ' /A << '.$pl['opt']['a'].' >>';
}
if (isset($pl['opt']['aa']) AND !empty($pl['opt']['aa'])) {
$annots .= ' /AA << '.$pl['opt']['aa'].' >>';
}
if (isset($pl['opt']['da']) AND !empty($pl['opt']['da'])) {
$annots .= ' /DA ('.$pl['opt']['da'].')';
}
if (isset($pl['opt']['q']) AND ($pl['opt']['q'] >= 0) AND ($pl['opt']['q'] <= 2)) {
$annots .= ' /Q '.intval($pl['opt']['q']);
}
if (isset($pl['opt']['opt']) AND (is_array($pl['opt']['opt'])) AND !empty($pl['opt']['opt'])) {
$annots .= ' /Opt [';
foreach($pl['opt']['opt'] AS $copt) {
if (is_array($copt)) {
$annots .= ' ['.$this->_textstring($copt[0], $annot_obj_id).' '.$this->_textstring($copt[1], $annot_obj_id).']';
} else {
$annots .= ' '.$this->_textstring($copt, $annot_obj_id);
}
}
$annots .= ']';
}
if (isset($pl['opt']['ti'])) {
$annots .= ' /TI '.intval($pl['opt']['ti']);
}
if (isset($pl['opt']['i']) AND (is_array($pl['opt']['i'])) AND !empty($pl['opt']['i'])) {
$annots .= ' /I [';
foreach($pl['opt']['i'] AS $copt) {
$annots .= intval($copt).' ';
}
$annots .= ']';
}
break;
}
case 'screen': {
break;
}
case 'printermark': {
break;
}
case 'trapnet': {
break;
}
case 'watermark': {
break;
}
case '3d': {
break;
}
default: {
break;
}
}
$annots .= '>>';
$this->_out($this->_getobj($annot_obj_id)."\n".$annots."\n".'endobj');
if ($formfield AND !isset($this->radiobutton_groups[$n][$pl['txt']])) {
$this->form_obj_id[] = $annot_obj_id;
}
}
}
}
}
protected function _putAPXObject($w=0, $h=0, $stream='') {
$stream = trim($stream);
$out = $this->_getobj()."\n";
$this->xobjects['AX'.$this->n] = array('n' => $this->n);
$out .= '<<';
$out .= ' /Type /XObject';
$out .= ' /Subtype /Form';
$out .= ' /FormType 1';
if ($this->compress) {
$stream = gzcompress($stream);
$out .= ' /Filter /FlateDecode';
}
$rect = sprintf('%F %F', $w, $h);
$out .= ' /BBox [0 0 '.$rect.']';
$out .= ' /Matrix [1 0 0 1 0 0]';
$out .= ' /Resources 2 0 R';
$stream = $this->_getrawstream($stream);
$out .= ' /Length '.strlen($stream);
$out .= ' >>';
$out .= ' stream'."\n".$stream."\n".'endstream';
$out .= "\n".'endobj';
$this->_out($out);
return $this->n;
}
protected function _putfonts() {
$nf = $this->n;
foreach ($this->diffs as $diff) {
$this->_newobj();
$this->_out('<< /Type /Encoding /BaseEncoding /WinAnsiEncoding /Differences ['.$diff.'] >>'."\n".'endobj');
}
$mqr = TCPDF_STATIC::get_mqr();
TCPDF_STATIC::set_mqr(false);
foreach ($this->FontFiles as $file => $info) {
$fontfile = TCPDF_FONTS::getFontFullPath($file, $info['fontdir']);
if (!TCPDF_STATIC::empty_string($fontfile)) {
$font = file_get_contents($fontfile);
$compressed = (substr($file, -2) == '.z');
if ((!$compressed) AND (isset($info['length2']))) {
$header = (ord($font[0]) == 128);
if ($header) {
$font = substr($font, 6);
}
if ($header AND (ord($font[$info['length1']]) == 128)) {
$font = substr($font, 0, $info['length1']).substr($font, ($info['length1'] + 6));
}
} elseif ($info['subset'] AND ((!$compressed) OR ($compressed AND function_exists('gzcompress')))) {
if ($compressed) {
$font = gzuncompress($font);
}
$subsetchars = array();
foreach ($info['fontkeys'] as $fontkey) {
$fontinfo = $this->getFontBuffer($fontkey);
$subsetchars += $fontinfo['subsetchars'];
}
$font = TCPDF_FONTS::_getTrueTypeFontSubset($font, $subsetchars);
$info['length1'] = strlen($font);
if ($compressed) {
$font = gzcompress($font);
}
}
$this->_newobj();
$this->FontFiles[$file]['n'] = $this->n;
$stream = $this->_getrawstream($font);
$out = '<< /Length '.strlen($stream);
if ($compressed) {
$out .= ' /Filter /FlateDecode';
}
$out .= ' /Length1 '.$info['length1'];
if (isset($info['length2'])) {
$out .= ' /Length2 '.$info['length2'].' /Length3 0';
}
$out .= ' >>';
$out .= ' stream'."\n".$stream."\n".'endstream';
$out .= "\n".'endobj';
$this->_out($out);
}
}
TCPDF_STATIC::set_mqr($mqr);
foreach ($this->fontkeys as $k) {
$font = $this->getFontBuffer($k);
$type = $font['type'];
$name = $font['name'];
if ($type == 'core') {
$out = $this->_getobj($this->font_obj_ids[$k])."\n";
$out .= '<</Type /Font';
$out .= ' /Subtype /Type1';
$out .= ' /BaseFont /'.$name;
$out .= ' /Name /F'.$font['i'];
if ((strtolower($name) != 'symbol') AND (strtolower($name) != 'zapfdingbats')) {
$out .= ' /Encoding /WinAnsiEncoding';
}
if ($k == 'helvetica') {
$this->annotation_fonts[$k] = $font['i'];
}
$out .= ' >>';
$out .= "\n".'endobj';
$this->_out($out);
} elseif (($type == 'Type1') OR ($type == 'TrueType')) {
$out = $this->_getobj($this->font_obj_ids[$k])."\n";
$out .= '<</Type /Font';
$out .= ' /Subtype /'.$type;
$out .= ' /BaseFont /'.$name;
$out .= ' /Name /F'.$font['i'];
$out .= ' /FirstChar 32 /LastChar 255';
$out .= ' /Widths '.($this->n + 1).' 0 R';
$out .= ' /FontDescriptor '.($this->n + 2).' 0 R';
if ($font['enc']) {
if (isset($font['diff'])) {
$out .= ' /Encoding '.($nf + $font['diff']).' 0 R';
} else {
$out .= ' /Encoding /WinAnsiEncoding';
}
}
$out .= ' >>';
$out .= "\n".'endobj';
$this->_out($out);
$this->_newobj();
$s = '[';
for ($i = 32; $i < 256; ++$i) {
if (isset($font['cw'][$i])) {
$s .= $font['cw'][$i].' ';
} else {
$s .= $font['dw'].' ';
}
}
$s .= ']';
$s .= "\n".'endobj';
$this->_out($s);
$this->_newobj();
$s = '<</Type /FontDescriptor /FontName /'.$name;
foreach ($font['desc'] as $fdk => $fdv) {
if (is_float($fdv)) {
$fdv = sprintf('%F', $fdv);
}
$s .= ' /'.$fdk.' '.$fdv.'';
}
if (!TCPDF_STATIC::empty_string($font['file'])) {
$s .= ' /FontFile'.($type == 'Type1' ? '' : '2').' '.$this->FontFiles[$font['file']]['n'].' 0 R';
}
$s .= '>>';
$s .= "\n".'endobj';
$this->_out($s);
} else {
$mtd = '_put'.strtolower($type);
if (!method_exists($this, $mtd)) {
$this->Error('Unsupported font type: '.$type);
}
$this->$mtd($font);
}
}
}
protected function _puttruetypeunicode($font) {
$fontname = '';
if ($font['subset']) {
$subtag = sprintf('%06u', $font['i']);
$subtag = strtr($subtag, '0123456789', 'ABCDEFGHIJ');
$fontname .= $subtag.'+';
}
$fontname .= $font['name'];
$out = $this->_getobj($this->font_obj_ids[$font['fontkey']])."\n";
$out .= '<< /Type /Font';
$out .= ' /Subtype /Type0';
$out .= ' /BaseFont /'.$fontname;
$out .= ' /Name /F'.$font['i'];
$out .= ' /Encoding /'.$font['enc'];
$out .= ' /ToUnicode '.($this->n + 1).' 0 R';
$out .= ' /DescendantFonts ['.($this->n + 2).' 0 R]';
$out .= ' >>';
$out .= "\n".'endobj';
$this->_out($out);
$stream = TCPDF_FONT_DATA::$uni_identity_h;
$this->_newobj();
$stream = ($this->compress) ? gzcompress($stream) : $stream;
$filter = ($this->compress) ? '/Filter /FlateDecode ' : '';
$stream = $this->_getrawstream($stream);
$this->_out('<<'.$filter.'/Length '.strlen($stream).'>> stream'."\n".$stream."\n".'endstream'."\n".'endobj');
$oid = $this->_newobj();
$out = '<< /Type /Font';
$out .= ' /Subtype /CIDFontType2';
$out .= ' /BaseFont /'.$fontname;
$cidinfo = '/Registry '.$this->_datastring($font['cidinfo']['Registry'], $oid);
$cidinfo .= ' /Ordering '.$this->_datastring($font['cidinfo']['Ordering'], $oid);
$cidinfo .= ' /Supplement '.$font['cidinfo']['Supplement'];
$out .= ' /CIDSystemInfo << '.$cidinfo.' >>';
$out .= ' /FontDescriptor '.($this->n + 1).' 0 R';
$out .= ' /DW '.$font['dw'];
$out .= "\n".TCPDF_FONTS::_putfontwidths($font, 0);
if (isset($font['ctg']) AND (!TCPDF_STATIC::empty_string($font['ctg']))) {
$out .= "\n".'/CIDToGIDMap '.($this->n + 2).' 0 R';
}
$out .= ' >>';
$out .= "\n".'endobj';
$this->_out($out);
$this->_newobj();
$out = '<< /Type /FontDescriptor';
$out .= ' /FontName /'.$fontname;
foreach ($font['desc'] as $key => $value) {
if (is_float($value)) {
$value = sprintf('%F', $value);
}
$out .= ' /'.$key.' '.$value;
}
$fontdir = false;
if (!TCPDF_STATIC::empty_string($font['file'])) {
$out .= ' /FontFile2 '.$this->FontFiles[$font['file']]['n'].' 0 R';
$fontdir = $this->FontFiles[$font['file']]['fontdir'];
}
$out .= ' >>';
$out .= "\n".'endobj';
$this->_out($out);
if (isset($font['ctg']) AND (!TCPDF_STATIC::empty_string($font['ctg']))) {
$this->_newobj();
$ctgfile = strtolower($font['ctg']);
$fontfile = TCPDF_FONTS::getFontFullPath($ctgfile, $fontdir);
if (TCPDF_STATIC::empty_string($fontfile)) {
$this->Error('Font file not found: '.$ctgfile);
}
$stream = $this->_getrawstream(file_get_contents($fontfile));
$out = '<< /Length '.strlen($stream).'';
if (substr($fontfile, -2) == '.z') {
$out .= ' /Filter /FlateDecode';
}
$out .= ' >>';
$out .= ' stream'."\n".$stream."\n".'endstream';
$out .= "\n".'endobj';
$this->_out($out);
}
}
protected function _putcidfont0($font) {
$cidoffset = 0;
if (!isset($font['cw'][1])) {
$cidoffset = 31;
}
if (isset($font['cidinfo']['uni2cid'])) {
$uni2cid = $font['cidinfo']['uni2cid'];
$cw = array();
foreach ($font['cw'] as $uni => $width) {
if (isset($uni2cid[$uni])) {
$cw[($uni2cid[$uni] + $cidoffset)] = $width;
} elseif ($uni < 256) {
$cw[$uni] = $width;
}
}
$font = array_merge($font, array('cw' => $cw));
}
$name = $font['name'];
$enc = $font['enc'];
if ($enc) {
$longname = $name.'-'.$enc;
} else {
$longname = $name;
}
$out = $this->_getobj($this->font_obj_ids[$font['fontkey']])."\n";
$out .= '<</Type /Font';
$out .= ' /Subtype /Type0';
$out .= ' /BaseFont /'.$longname;
$out .= ' /Name /F'.$font['i'];
if ($enc) {
$out .= ' /Encoding /'.$enc;
}
$out .= ' /DescendantFonts ['.($this->n + 1).' 0 R]';
$out .= ' >>';
$out .= "\n".'endobj';
$this->_out($out);
$oid = $this->_newobj();
$out = '<</Type /Font';
$out .= ' /Subtype /CIDFontType0';
$out .= ' /BaseFont /'.$name;
$cidinfo = '/Registry '.$this->_datastring($font['cidinfo']['Registry'], $oid);
$cidinfo .= ' /Ordering '.$this->_datastring($font['cidinfo']['Ordering'], $oid);
$cidinfo .= ' /Supplement '.$font['cidinfo']['Supplement'];
$out .= ' /CIDSystemInfo <<'.$cidinfo.'>>';
$out .= ' /FontDescriptor '.($this->n + 1).' 0 R';
$out .= ' /DW '.$font['dw'];
$out .= "\n".TCPDF_FONTS::_putfontwidths($font, $cidoffset);
$out .= ' >>';
$out .= "\n".'endobj';
$this->_out($out);
$this->_newobj();
$s = '<</Type /FontDescriptor /FontName /'.$name;
foreach ($font['desc'] as $k => $v) {
if ($k != 'Style') {
if (is_float($v)) {
$v = sprintf('%F', $v);
}
$s .= ' /'.$k.' '.$v.'';
}
}
$s .= '>>';
$s .= "\n".'endobj';
$this->_out($s);
}
protected function _putimages() {
$filter = ($this->compress) ? '/Filter /FlateDecode ' : '';
foreach ($this->imagekeys as $file) {
$info = $this->getImageBuffer($file);
if ((!$this->pdfa_mode) AND isset($info['altimgs']) AND !empty($info['altimgs'])) {
$altoid = $this->_newobj();
$out = '[';
foreach ($info['altimgs'] as $altimage) {
if (isset($this->xobjects['I'.$altimage[0]]['n'])) {
$out .= ' << /Image '.$this->xobjects['I'.$altimage[0]]['n'].' 0 R';
$out .= ' /DefaultForPrinting';
if ($altimage[1] === true) {
$out .= ' true';
} else {
$out .= ' false';
}
$out .= ' >>';
}
}
$out .= ' ]';
$out .= "\n".'endobj';
$this->_out($out);
}
$oid = $this->_newobj();
$this->xobjects['I'.$info['i']] = array('n' => $oid);
$this->setImageSubBuffer($file, 'n', $this->n);
$out = '<</Type /XObject';
$out .= ' /Subtype /Image';
$out .= ' /Width '.$info['w'];
$out .= ' /Height '.$info['h'];
if (array_key_exists('masked', $info)) {
$out .= ' /SMask '.($this->n - 1).' 0 R';
}
$icc = false;
if (isset($info['icc']) AND ($info['icc'] !== false)) {
$icc = true;
$out .= ' /ColorSpace [/ICCBased '.($this->n + 1).' 0 R]';
} elseif ($info['cs'] == 'Indexed') {
$out .= ' /ColorSpace [/Indexed /DeviceRGB '.((strlen($info['pal']) / 3) - 1).' '.($this->n + 1).' 0 R]';
} else {
$out .= ' /ColorSpace /'.$info['cs'];
}
if ($info['cs'] == 'DeviceCMYK') {
$out .= ' /Decode [1 0 1 0 1 0 1 0]';
}
$out .= ' /BitsPerComponent '.$info['bpc'];
if (isset($altoid) AND ($altoid > 0)) {
$out .= ' /Alternates '.$altoid.' 0 R';
}
if (isset($info['exurl']) AND !empty($info['exurl'])) {
$out .= ' /Length 0';
$out .= ' /F << /FS /URL /F '.$this->_datastring($info['exurl'], $oid).' >>';
if (isset($info['f'])) {
$out .= ' /FFilter /'.$info['f'];
}
$out .= ' >>';
$out .= ' stream'."\n".'endstream';
} else {
if (isset($info['f'])) {
$out .= ' /Filter /'.$info['f'];
}
if (isset($info['parms'])) {
$out .= ' '.$info['parms'];
}
if (isset($info['trns']) AND is_array($info['trns'])) {
$trns = '';
$count_info = count($info['trns']);
if ($info['cs'] == 'Indexed') {
$maxval =(pow(2, $info['bpc']) - 1);
for ($i = 0; $i < $count_info; ++$i) {
if (($info['trns'][$i] != 0) AND ($info['trns'][$i] != $maxval)) {
$trns = '';
break;
} elseif (empty($trns) AND ($info['trns'][$i] == 0)) {
$trns .= $i.' '.$i.' ';
}
}
} else {
for ($i = 0; $i < $count_info; ++$i) {
if ($info['trns'][$i] == 0) {
$trns .= $info['trns'][$i].' '.$info['trns'][$i].' ';
}
}
}
if (!empty($trns)) {
$out .= ' /Mask ['.$trns.']';
}
}
$stream = $this->_getrawstream($info['data']);
$out .= ' /Length '.strlen($stream).' >>';
$out .= ' stream'."\n".$stream."\n".'endstream';
}
$out .= "\n".'endobj';
$this->_out($out);
if ($icc) {
$this->_newobj();
$icc = ($this->compress) ? gzcompress($info['icc']) : $info['icc'];
$icc = $this->_getrawstream($icc);
$this->_out('<</N '.$info['ch'].' /Alternate /'.$info['cs'].' '.$filter.'/Length '.strlen($icc).'>> stream'."\n".$icc."\n".'endstream'."\n".'endobj');
} elseif ($info['cs'] == 'Indexed') {
$this->_newobj();
$pal = ($this->compress) ? gzcompress($info['pal']) : $info['pal'];
$pal = $this->_getrawstream($pal);
$this->_out('<<'.$filter.'/Length '.strlen($pal).'>> stream'."\n".$pal."\n".'endstream'."\n".'endobj');
}
}
}
protected function _putxobjects() {
foreach ($this->xobjects as $key => $data) {
if (isset($data['outdata'])) {
$stream = str_replace($this->epsmarker, '', trim($data['outdata']));
$out = $this->_getobj($data['n'])."\n";
$out .= '<<';
$out .= ' /Type /XObject';
$out .= ' /Subtype /Form';
$out .= ' /FormType 1';
if ($this->compress) {
$stream = gzcompress($stream);
$out .= ' /Filter /FlateDecode';
}
$out .= sprintf(' /BBox [%F %F %F %F]', ($data['x'] * $this->k), (-$data['y'] * $this->k), (($data['w'] + $data['x']) * $this->k), (($data['h'] - $data['y']) * $this->k));
$out .= ' /Matrix [1 0 0 1 0 0]';
$out .= ' /Resources <<';
$out .= ' /ProcSet [/PDF /Text /ImageB /ImageC /ImageI]';
if (!$this->pdfa_mode) {
if (isset($data['extgstates']) AND !empty($data['extgstates'])) {
$out .= ' /ExtGState <<';
foreach ($data['extgstates'] as $k => $extgstate) {
if (isset($this->extgstates[$k]['name'])) {
$out .= ' /'.$this->extgstates[$k]['name'];
} else {
$out .= ' /GS'.$k;
}
$out .= ' '.$this->extgstates[$k]['n'].' 0 R';
}
$out .= ' >>';
}
if (isset($data['gradients']) AND !empty($data['gradients'])) {
$gp = '';
$gs = '';
foreach ($data['gradients'] as $id => $grad) {
$gp .= ' /p'.$id.' '.$this->gradients[$id]['pattern'].' 0 R';
$gs .= ' /Sh'.$id.' '.$this->gradients[$id]['id'].' 0 R';
}
$out .= ' /Pattern <<'.$gp.' >>';
$out .= ' /Shading <<'.$gs.' >>';
}
}
if (isset($data['spot_colors']) AND !empty($data['spot_colors'])) {
$out .= ' /ColorSpace <<';
foreach ($data['spot_colors'] as $name => $color) {
$out .= ' /CS'.$color['i'].' '.$this->spot_colors[$name]['n'].' 0 R';
}
$out .= ' >>';
}
if (!empty($data['fonts'])) {
$out .= ' /Font <<';
foreach ($data['fonts'] as $fontkey => $fontid) {
$out .= ' /F'.$fontid.' '.$this->font_obj_ids[$fontkey].' 0 R';
}
$out .= ' >>';
}
if (!empty($data['images']) OR !empty($data['xobjects'])) {
$out .= ' /XObject <<';
foreach ($data['images'] as $imgid) {
$out .= ' /I'.$imgid.' '.$this->xobjects['I'.$imgid]['n'].' 0 R';
}
foreach ($data['xobjects'] as $sub_id => $sub_objid) {
$out .= ' /'.$sub_id.' '.$sub_objid['n'].' 0 R';
}
$out .= ' >>';
}
$out .= ' >>';
if (isset($data['group']) AND ($data['group'] !== false)) {
$out .= ' /Group << /Type /Group /S /Transparency';
if (is_array($data['group'])) {
if (isset($data['group']['CS']) AND !empty($data['group']['CS'])) {
$out .= ' /CS /'.$data['group']['CS'];
}
if (isset($data['group']['I'])) {
$out .= ' /I /'.($data['group']['I']===true?'true':'false');
}
if (isset($data['group']['K'])) {
$out .= ' /K /'.($data['group']['K']===true?'true':'false');
}
}
$out .= ' >>';
}
$stream = $this->_getrawstream($stream, $data['n']);
$out .= ' /Length '.strlen($stream);
$out .= ' >>';
$out .= ' stream'."\n".$stream."\n".'endstream';
$out .= "\n".'endobj';
$this->_out($out);
}
}
}
protected function _putspotcolors() {
foreach ($this->spot_colors as $name => $color) {
$this->_newobj();
$this->spot_colors[$name]['n'] = $this->n;
$out = '[/Separation /'.str_replace(' ', '#20', $name);
$out .= ' /DeviceCMYK <<';
$out .= ' /Range [0 1 0 1 0 1 0 1] /C0 [0 0 0 0]';
$out .= ' '.sprintf('/C1 [%F %F %F %F] ', ($color['C'] / 100), ($color['M'] / 100), ($color['Y'] / 100), ($color['K'] / 100));
$out .= ' /FunctionType 2 /Domain [0 1] /N 1>>]';
$out .= "\n".'endobj';
$this->_out($out);
}
}
protected function _getxobjectdict() {
$out = '';
foreach ($this->xobjects as $id => $objid) {
$out .= ' /'.$id.' '.$objid['n'].' 0 R';
}
return $out;
}
protected function _putresourcedict() {
$out = $this->_getobj(2)."\n";
$out .= '<< /ProcSet [/PDF /Text /ImageB /ImageC /ImageI]';
$out .= ' /Font <<';
foreach ($this->fontkeys as $fontkey) {
$font = $this->getFontBuffer($fontkey);
$out .= ' /F'.$font['i'].' '.$font['n'].' 0 R';
}
$out .= ' >>';
$out .= ' /XObject <<';
$out .= $this->_getxobjectdict();
$out .= ' >>';
if (!empty($this->pdflayers)) {
$out .= ' /Properties <<';
foreach ($this->pdflayers as $layer) {
$out .= ' /'.$layer['layer'].' '.$layer['objid'].' 0 R';
}
$out .= ' >>';
}
if (!$this->pdfa_mode) {
if (isset($this->extgstates) AND !empty($this->extgstates)) {
$out .= ' /ExtGState <<';
foreach ($this->extgstates as $k => $extgstate) {
if (isset($extgstate['name'])) {
$out .= ' /'.$extgstate['name'];
} else {
$out .= ' /GS'.$k;
}
$out .= ' '.$extgstate['n'].' 0 R';
}
$out .= ' >>';
}
if (isset($this->gradients) AND !empty($this->gradients)) {
$gp = '';
$gs = '';
foreach ($this->gradients as $id => $grad) {
$gp .= ' /p'.$id.' '.$grad['pattern'].' 0 R';
$gs .= ' /Sh'.$id.' '.$grad['id'].' 0 R';
}
$out .= ' /Pattern <<'.$gp.' >>';
$out .= ' /Shading <<'.$gs.' >>';
}
}
if (isset($this->spot_colors) AND !empty($this->spot_colors)) {
$out .= ' /ColorSpace <<';
foreach ($this->spot_colors as $color) {
$out .= ' /CS'.$color['i'].' '.$color['n'].' 0 R';
}
$out .= ' >>';
}
$out .= ' >>';
$out .= "\n".'endobj';
$this->_out($out);
}
protected function _putresources() {
$this->_putextgstates();
$this->_putocg();
$this->_putfonts();
$this->_putimages();
$this->_putspotcolors();
$this->_putshaders();
$this->_putxobjects();
$this->_putresourcedict();
$this->_putdests();
$this->_putEmbeddedFiles();
$this->_putannotsobjs();
$this->_putjavascript();
$this->_putbookmarks();
$this->_putencryption();
}
protected function _putinfo() {
$oid = $this->_newobj();
$out = '<<';
$prev_isunicode = $this->isunicode;
if ($this->docinfounicode) {
$this->isunicode = true;
}
if (!TCPDF_STATIC::empty_string($this->title)) {
$out .= ' /Title '.$this->_textstring($this->title, $oid);
}
if (!TCPDF_STATIC::empty_string($this->author)) {
$out .= ' /Author '.$this->_textstring($this->author, $oid);
}
if (!TCPDF_STATIC::empty_string($this->subject)) {
$out .= ' /Subject '.$this->_textstring($this->subject, $oid);
}
if (!TCPDF_STATIC::empty_string($this->keywords)) {
$out .= ' /Keywords '.$this->_textstring($this->keywords, $oid);
}
if (!TCPDF_STATIC::empty_string($this->creator)) {
$out .= ' /Creator '.$this->_textstring($this->creator, $oid);
}
$this->isunicode = $prev_isunicode;
$out .= ' /Producer '.$this->_textstring(TCPDF_STATIC::getTCPDFProducer(), $oid);
$out .= ' /CreationDate '.$this->_datestring(0, $this->doc_creation_timestamp);
$out .= ' /ModDate '.$this->_datestring(0, $this->doc_modification_timestamp);
$out .= ' /Trapped /False';
$out .= ' >>';
$out .= "\n".'endobj';
$this->_out($out);
return $oid;
}
public function setExtraXMP($xmp) {
$this->custom_xmp = $xmp;
}
protected function _putXMP() {
$oid = $this->_newobj();
$prev_isunicode = $this->isunicode;
$this->isunicode = true;
$prev_encrypted = $this->encrypted;
$this->encrypted = false;
$xmp = '<?xpacket begin="'.TCPDF_FONTS::unichr(0xfeff, $this->isunicode).'" id="W5M0MpCehiHzreSzNTczkc9d"?>'."\n";
$xmp .= '<x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="Adobe XMP Core 4.2.1-c043 52.372728, 2009/01/18-15:08:04">'."\n";
$xmp .= "\t".'<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">'."\n";
$xmp .= "\t\t".'<rdf:Description rdf:about="" xmlns:dc="http://purl.org/dc/elements/1.1/">'."\n";
$xmp .= "\t\t\t".'<dc:format>application/pdf</dc:format>'."\n";
$xmp .= "\t\t\t".'<dc:title>'."\n";
$xmp .= "\t\t\t\t".'<rdf:Alt>'."\n";
$xmp .= "\t\t\t\t\t".'<rdf:li xml:lang="x-default">'.TCPDF_STATIC::_escapeXML($this->title).'</rdf:li>'."\n";
$xmp .= "\t\t\t\t".'</rdf:Alt>'."\n";
$xmp .= "\t\t\t".'</dc:title>'."\n";
$xmp .= "\t\t\t".'<dc:creator>'."\n";
$xmp .= "\t\t\t\t".'<rdf:Seq>'."\n";
$xmp .= "\t\t\t\t\t".'<rdf:li>'.TCPDF_STATIC::_escapeXML($this->author).'</rdf:li>'."\n";
$xmp .= "\t\t\t\t".'</rdf:Seq>'."\n";
$xmp .= "\t\t\t".'</dc:creator>'."\n";
$xmp .= "\t\t\t".'<dc:description>'."\n";
$xmp .= "\t\t\t\t".'<rdf:Alt>'."\n";
$xmp .= "\t\t\t\t\t".'<rdf:li xml:lang="x-default">'.TCPDF_STATIC::_escapeXML($this->subject).'</rdf:li>'."\n";
$xmp .= "\t\t\t\t".'</rdf:Alt>'."\n";
$xmp .= "\t\t\t".'</dc:description>'."\n";
$xmp .= "\t\t\t".'<dc:subject>'."\n";
$xmp .= "\t\t\t\t".'<rdf:Bag>'."\n";
$xmp .= "\t\t\t\t\t".'<rdf:li>'.TCPDF_STATIC::_escapeXML($this->keywords).'</rdf:li>'."\n";
$xmp .= "\t\t\t\t".'</rdf:Bag>'."\n";
$xmp .= "\t\t\t".'</dc:subject>'."\n";
$xmp .= "\t\t".'</rdf:Description>'."\n";
$dcdate = TCPDF_STATIC::getFormattedDate($this->doc_creation_timestamp);
$doccreationdate = substr($dcdate, 0, 4).'-'.substr($dcdate, 4, 2).'-'.substr($dcdate, 6, 2);
$doccreationdate .= 'T'.substr($dcdate, 8, 2).':'.substr($dcdate, 10, 2).':'.substr($dcdate, 12, 2);
$doccreationdate .= substr($dcdate, 14, 3).':'.substr($dcdate, 18, 2);
$doccreationdate = TCPDF_STATIC::_escapeXML($doccreationdate);
$dmdate = TCPDF_STATIC::getFormattedDate($this->doc_modification_timestamp);
$docmoddate = substr($dmdate, 0, 4).'-'.substr($dmdate, 4, 2).'-'.substr($dmdate, 6, 2);
$docmoddate .= 'T'.substr($dmdate, 8, 2).':'.substr($dmdate, 10, 2).':'.substr($dmdate, 12, 2);
$docmoddate .= substr($dmdate, 14, 3).':'.substr($dmdate, 18, 2);
$docmoddate = TCPDF_STATIC::_escapeXML($docmoddate);
$xmp .= "\t\t".'<rdf:Description rdf:about="" xmlns:xmp="http://ns.adobe.com/xap/1.0/">'."\n";
$xmp .= "\t\t\t".'<xmp:CreateDate>'.$doccreationdate.'</xmp:CreateDate>'."\n";
$xmp .= "\t\t\t".'<xmp:CreatorTool>'.$this->creator.'</xmp:CreatorTool>'."\n";
$xmp .= "\t\t\t".'<xmp:ModifyDate>'.$docmoddate.'</xmp:ModifyDate>'."\n";
$xmp .= "\t\t\t".'<xmp:MetadataDate>'.$doccreationdate.'</xmp:MetadataDate>'."\n";
$xmp .= "\t\t".'</rdf:Description>'."\n";
$xmp .= "\t\t".'<rdf:Description rdf:about="" xmlns:pdf="http://ns.adobe.com/pdf/1.3/">'."\n";
$xmp .= "\t\t\t".'<pdf:Keywords>'.TCPDF_STATIC::_escapeXML($this->keywords).'</pdf:Keywords>'."\n";
$xmp .= "\t\t\t".'<pdf:Producer>'.TCPDF_STATIC::_escapeXML(TCPDF_STATIC::getTCPDFProducer()).'</pdf:Producer>'."\n";
$xmp .= "\t\t".'</rdf:Description>'."\n";
$xmp .= "\t\t".'<rdf:Description rdf:about="" xmlns:xmpMM="http://ns.adobe.com/xap/1.0/mm/">'."\n";
$uuid = 'uuid:'.substr($this->file_id, 0, 8).'-'.substr($this->file_id, 8, 4).'-'.substr($this->file_id, 12, 4).'-'.substr($this->file_id, 16, 4).'-'.substr($this->file_id, 20, 12);
$xmp .= "\t\t\t".'<xmpMM:DocumentID>'.$uuid.'</xmpMM:DocumentID>'."\n";
$xmp .= "\t\t\t".'<xmpMM:InstanceID>'.$uuid.'</xmpMM:InstanceID>'."\n";
$xmp .= "\t\t".'</rdf:Description>'."\n";
if ($this->pdfa_mode) {
$xmp .= "\t\t".'<rdf:Description rdf:about="" xmlns:pdfaid="http://www.aiim.org/pdfa/ns/id/">'."\n";
$xmp .= "\t\t\t".'<pdfaid:part>1</pdfaid:part>'."\n";
$xmp .= "\t\t\t".'<pdfaid:conformance>B</pdfaid:conformance>'."\n";
$xmp .= "\t\t".'</rdf:Description>'."\n";
}
$xmp .= "\t\t".'<rdf:Description rdf:about="" xmlns:pdfaExtension="http://www.aiim.org/pdfa/ns/extension/" xmlns:pdfaSchema="http://www.aiim.org/pdfa/ns/schema#" xmlns:pdfaProperty="http://www.aiim.org/pdfa/ns/property#">'."\n";
$xmp .= "\t\t\t".'<pdfaExtension:schemas>'."\n";
$xmp .= "\t\t\t\t".'<rdf:Bag>'."\n";
$xmp .= "\t\t\t\t\t".'<rdf:li rdf:parseType="Resource">'."\n";
$xmp .= "\t\t\t\t\t\t".'<pdfaSchema:namespaceURI>http://ns.adobe.com/pdf/1.3/</pdfaSchema:namespaceURI>'."\n";
$xmp .= "\t\t\t\t\t\t".'<pdfaSchema:prefix>pdf</pdfaSchema:prefix>'."\n";
$xmp .= "\t\t\t\t\t\t".'<pdfaSchema:schema>Adobe PDF Schema</pdfaSchema:schema>'."\n";
$xmp .= "\t\t\t\t\t".'</rdf:li>'."\n";
$xmp .= "\t\t\t\t\t".'<rdf:li rdf:parseType="Resource">'."\n";
$xmp .= "\t\t\t\t\t\t".'<pdfaSchema:namespaceURI>http://ns.adobe.com/xap/1.0/mm/</pdfaSchema:namespaceURI>'."\n";
$xmp .= "\t\t\t\t\t\t".'<pdfaSchema:prefix>xmpMM</pdfaSchema:prefix>'."\n";
$xmp .= "\t\t\t\t\t\t".'<pdfaSchema:schema>XMP Media Management Schema</pdfaSchema:schema>'."\n";
$xmp .= "\t\t\t\t\t\t".'<pdfaSchema:property>'."\n";
$xmp .= "\t\t\t\t\t\t\t".'<rdf:Seq>'."\n";
$xmp .= "\t\t\t\t\t\t\t\t".'<rdf:li rdf:parseType="Resource">'."\n";
$xmp .= "\t\t\t\t\t\t\t\t\t".'<pdfaProperty:category>internal</pdfaProperty:category>'."\n";
$xmp .= "\t\t\t\t\t\t\t\t\t".'<pdfaProperty:description>UUID based identifier for specific incarnation of a document</pdfaProperty:description>'."\n";
$xmp .= "\t\t\t\t\t\t\t\t\t".'<pdfaProperty:name>InstanceID</pdfaProperty:name>'."\n";
$xmp .= "\t\t\t\t\t\t\t\t\t".'<pdfaProperty:valueType>URI</pdfaProperty:valueType>'."\n";
$xmp .= "\t\t\t\t\t\t\t\t".'</rdf:li>'."\n";
$xmp .= "\t\t\t\t\t\t\t".'</rdf:Seq>'."\n";
$xmp .= "\t\t\t\t\t\t".'</pdfaSchema:property>'."\n";
$xmp .= "\t\t\t\t\t".'</rdf:li>'."\n";
$xmp .= "\t\t\t\t\t".'<rdf:li rdf:parseType="Resource">'."\n";
$xmp .= "\t\t\t\t\t\t".'<pdfaSchema:namespaceURI>http://www.aiim.org/pdfa/ns/id/</pdfaSchema:namespaceURI>'."\n";
$xmp .= "\t\t\t\t\t\t".'<pdfaSchema:prefix>pdfaid</pdfaSchema:prefix>'."\n";
$xmp .= "\t\t\t\t\t\t".'<pdfaSchema:schema>PDF/A ID Schema</pdfaSchema:schema>'."\n";
$xmp .= "\t\t\t\t\t\t".'<pdfaSchema:property>'."\n";
$xmp .= "\t\t\t\t\t\t\t".'<rdf:Seq>'."\n";
$xmp .= "\t\t\t\t\t\t\t\t".'<rdf:li rdf:parseType="Resource">'."\n";
$xmp .= "\t\t\t\t\t\t\t\t\t".'<pdfaProperty:category>internal</pdfaProperty:category>'."\n";
$xmp .= "\t\t\t\t\t\t\t\t\t".'<pdfaProperty:description>Part of PDF/A standard</pdfaProperty:description>'."\n";
$xmp .= "\t\t\t\t\t\t\t\t\t".'<pdfaProperty:name>part</pdfaProperty:name>'."\n";
$xmp .= "\t\t\t\t\t\t\t\t\t".'<pdfaProperty:valueType>Integer</pdfaProperty:valueType>'."\n";
$xmp .= "\t\t\t\t\t\t\t\t".'</rdf:li>'."\n";
$xmp .= "\t\t\t\t\t\t\t\t".'<rdf:li rdf:parseType="Resource">'."\n";
$xmp .= "\t\t\t\t\t\t\t\t\t".'<pdfaProperty:category>internal</pdfaProperty:category>'."\n";
$xmp .= "\t\t\t\t\t\t\t\t\t".'<pdfaProperty:description>Amendment of PDF/A standard</pdfaProperty:description>'."\n";
$xmp .= "\t\t\t\t\t\t\t\t\t".'<pdfaProperty:name>amd</pdfaProperty:name>'."\n";
$xmp .= "\t\t\t\t\t\t\t\t\t".'<pdfaProperty:valueType>Text</pdfaProperty:valueType>'."\n";
$xmp .= "\t\t\t\t\t\t\t\t".'</rdf:li>'."\n";
$xmp .= "\t\t\t\t\t\t\t\t".'<rdf:li rdf:parseType="Resource">'."\n";
$xmp .= "\t\t\t\t\t\t\t\t\t".'<pdfaProperty:category>internal</pdfaProperty:category>'."\n";
$xmp .= "\t\t\t\t\t\t\t\t\t".'<pdfaProperty:description>Conformance level of PDF/A standard</pdfaProperty:description>'."\n";
$xmp .= "\t\t\t\t\t\t\t\t\t".'<pdfaProperty:name>conformance</pdfaProperty:name>'."\n";
$xmp .= "\t\t\t\t\t\t\t\t\t".'<pdfaProperty:valueType>Text</pdfaProperty:valueType>'."\n";
$xmp .= "\t\t\t\t\t\t\t\t".'</rdf:li>'."\n";
$xmp .= "\t\t\t\t\t\t\t".'</rdf:Seq>'."\n";
$xmp .= "\t\t\t\t\t\t".'</pdfaSchema:property>'."\n";
$xmp .= "\t\t\t\t\t".'</rdf:li>'."\n";
$xmp .= "\t\t\t\t".'</rdf:Bag>'."\n";
$xmp .= "\t\t\t".'</pdfaExtension:schemas>'."\n";
$xmp .= "\t\t".'</rdf:Description>'."\n";
$xmp .= "\t".'</rdf:RDF>'."\n";
$xmp .= $this->custom_xmp;
$xmp .= '</x:xmpmeta>'."\n";
$xmp .= '<?xpacket end="w"?>';
$out = '<< /Type /Metadata /Subtype /XML /Length '.strlen($xmp).' >> stream'."\n".$xmp."\n".'endstream'."\n".'endobj';
$this->isunicode = $prev_isunicode;
$this->encrypted = $prev_encrypted;
$this->_out($out);
return $oid;
}
protected function _putcatalog() {
$xmpobj = $this->_putXMP();
if ($this->pdfa_mode OR $this->force_srgb) {
$iccobj = $this->_newobj();
$icc = file_get_contents(dirname(__FILE__).'/include/sRGB.icc');
$filter = '';
if ($this->compress) {
$filter = ' /Filter /FlateDecode';
$icc = gzcompress($icc);
}
$icc = $this->_getrawstream($icc);
$this->_out('<</N 3 '.$filter.'/Length '.strlen($icc).'>> stream'."\n".$icc."\n".'endstream'."\n".'endobj');
}
$oid = $this->_newobj();
$out = '<< /Type /Catalog';
$out .= ' /Version /'.$this->PDFVersion;
$out .= ' /Pages 1 0 R';
$out .= ' /Names <<';
if ((!$this->pdfa_mode) AND !empty($this->n_js)) {
$out .= ' /JavaScript '.$this->n_js;
}
if (!empty($this->efnames)) {
$out .= ' /EmbeddedFiles <</Names [';
foreach ($this->efnames AS $fn => $fref) {
$out .= ' '.$this->_datastring($fn).' '.$fref;
}
$out .= ' ]>>';
}
$out .= ' >>';
if (!empty($this->dests)) {
$out .= ' /Dests '.($this->n_dests).' 0 R';
}
$out .= $this->_putviewerpreferences();
if (isset($this->LayoutMode) AND (!TCPDF_STATIC::empty_string($this->LayoutMode))) {
$out .= ' /PageLayout /'.$this->LayoutMode;
}
if (isset($this->PageMode) AND (!TCPDF_STATIC::empty_string($this->PageMode))) {
$out .= ' /PageMode /'.$this->PageMode;
}
if (count($this->outlines) > 0) {
$out .= ' /Outlines '.$this->OutlineRoot.' 0 R';
$out .= ' /PageMode /UseOutlines';
}
if ($this->ZoomMode == 'fullpage') {
$out .= ' /OpenAction ['.$this->page_obj_id[1].' 0 R /Fit]';
} elseif ($this->ZoomMode == 'fullwidth') {
$out .= ' /OpenAction ['.$this->page_obj_id[1].' 0 R /FitH null]';
} elseif ($this->ZoomMode == 'real') {
$out .= ' /OpenAction ['.$this->page_obj_id[1].' 0 R /XYZ null null 1]';
} elseif (!is_string($this->ZoomMode)) {
$out .= sprintf(' /OpenAction ['.$this->page_obj_id[1].' 0 R /XYZ null null %F]', ($this->ZoomMode / 100));
}
$out .= ' /Metadata '.$xmpobj.' 0 R';
if (isset($this->l['a_meta_language'])) {
$out .= ' /Lang '.$this->_textstring($this->l['a_meta_language'], $oid);
}
if ($this->pdfa_mode OR $this->force_srgb) {
$out .= ' /OutputIntents [<<';
$out .= ' /Type /OutputIntent';
$out .= ' /S /GTS_PDFA1';
$out .= ' /OutputCondition '.$this->_textstring('sRGB IEC61966-2.1', $oid);
$out .= ' /OutputConditionIdentifier '.$this->_textstring('sRGB IEC61966-2.1', $oid);
$out .= ' /RegistryName '.$this->_textstring('http://www.color.org', $oid);
$out .= ' /Info '.$this->_textstring('sRGB IEC61966-2.1', $oid);
$out .= ' /DestOutputProfile '.$iccobj.' 0 R';
$out .= ' >>]';
}
if (!empty($this->pdflayers)) {
$lyrobjs = '';
$lyrobjs_off = '';
$lyrobjs_lock = '';
foreach ($this->pdflayers as $layer) {
$layer_obj_ref = ' '.$layer['objid'].' 0 R';
$lyrobjs .= $layer_obj_ref;
if ($layer['view'] === false) {
$lyrobjs_off .= $layer_obj_ref;
}
if ($layer['lock']) {
$lyrobjs_lock .= $layer_obj_ref;
}
}
$out .= ' /OCProperties << /OCGs ['.$lyrobjs.']';
$out .= ' /D <<';
$out .= ' /Name '.$this->_textstring('Layers', $oid);
$out .= ' /Creator '.$this->_textstring('TCPDF', $oid);
$out .= ' /BaseState /ON';
$out .= ' /OFF ['.$lyrobjs_off.']';
$out .= ' /Locked ['.$lyrobjs_lock.']';
$out .= ' /Intent /View';
$out .= ' /AS [';
$out .= ' << /Event /Print /OCGs ['.$lyrobjs.'] /Category [/Print] >>';
$out .= ' << /Event /View /OCGs ['.$lyrobjs.'] /Category [/View] >>';
$out .= ' ]';
$out .= ' /Order ['.$lyrobjs.']';
$out .= ' /ListMode /AllPages';
$out .= ' >>';
$out .= ' >>';
}
if (!empty($this->form_obj_id)
OR ($this->sign AND isset($this->signature_data['cert_type']))
OR !empty($this->empty_signature_appearance)) {
$out .= ' /AcroForm <<';
$objrefs = '';
if ($this->sign AND isset($this->signature_data['cert_type'])) {
$objrefs .= $this->sig_obj_id.' 0 R';
}
if (!empty($this->empty_signature_appearance)) {
foreach ($this->empty_signature_appearance as $esa) {
$objrefs .= ' '.$esa['objid'].' 0 R';
}
}
if (!empty($this->form_obj_id)) {
foreach($this->form_obj_id as $objid) {
$objrefs .= ' '.$objid.' 0 R';
}
}
$out .= ' /Fields ['.$objrefs.']';
if (empty($this->signature_data['approval']) OR ($this->signature_data['approval'] != 'A')) {
$out .= ' /NeedAppearances false';
}
if ($this->sign AND isset($this->signature_data['cert_type'])) {
if ($this->signature_data['cert_type'] > 0) {
$out .= ' /SigFlags 3';
} else {
$out .= ' /SigFlags 1';
}
}
if (isset($this->annotation_fonts) AND !empty($this->annotation_fonts)) {
$out .= ' /DR <<';
$out .= ' /Font <<';
foreach ($this->annotation_fonts as $fontkey => $fontid) {
$out .= ' /F'.$fontid.' '.$this->font_obj_ids[$fontkey].' 0 R';
}
$out .= ' >> >>';
}
$font = $this->getFontBuffer('helvetica');
$out .= ' /DA (/F'.$font['i'].' 0 Tf 0 g)';
$out .= ' /Q '.(($this->rtl)?'2':'0');
$out .= ' >>';
if ($this->sign AND isset($this->signature_data['cert_type'])
AND (empty($this->signature_data['approval']) OR ($this->signature_data['approval'] != 'A'))) {
if ($this->signature_data['cert_type'] > 0) {
$out .= ' /Perms << /DocMDP '.($this->sig_obj_id + 1).' 0 R >>';
} else {
$out .= ' /Perms << /UR3 '.($this->sig_obj_id + 1).' 0 R >>';
}
}
}
$out .= ' >>';
$out .= "\n".'endobj';
$this->_out($out);
return $oid;
}
protected function _putviewerpreferences() {
$vp = $this->viewer_preferences;
$out = ' /ViewerPreferences <<';
if ($this->rtl) {
$out .= ' /Direction /R2L';
} else {
$out .= ' /Direction /L2R';
}
if (isset($vp['HideToolbar']) AND ($vp['HideToolbar'])) {
$out .= ' /HideToolbar true';
}
if (isset($vp['HideMenubar']) AND ($vp['HideMenubar'])) {
$out .= ' /HideMenubar true';
}
if (isset($vp['HideWindowUI']) AND ($vp['HideWindowUI'])) {
$out .= ' /HideWindowUI true';
}
if (isset($vp['FitWindow']) AND ($vp['FitWindow'])) {
$out .= ' /FitWindow true';
}
if (isset($vp['CenterWindow']) AND ($vp['CenterWindow'])) {
$out .= ' /CenterWindow true';
}
if (isset($vp['DisplayDocTitle']) AND ($vp['DisplayDocTitle'])) {
$out .= ' /DisplayDocTitle true';
}
if (isset($vp['NonFullScreenPageMode'])) {
$out .= ' /NonFullScreenPageMode /'.$vp['NonFullScreenPageMode'];
}
if (isset($vp['ViewArea'])) {
$out .= ' /ViewArea /'.$vp['ViewArea'];
}
if (isset($vp['ViewClip'])) {
$out .= ' /ViewClip /'.$vp['ViewClip'];
}
if (isset($vp['PrintArea'])) {
$out .= ' /PrintArea /'.$vp['PrintArea'];
}
if (isset($vp['PrintClip'])) {
$out .= ' /PrintClip /'.$vp['PrintClip'];
}
if (isset($vp['PrintScaling'])) {
$out .= ' /PrintScaling /'.$vp['PrintScaling'];
}
if (isset($vp['Duplex']) AND (!TCPDF_STATIC::empty_string($vp['Duplex']))) {
$out .= ' /Duplex /'.$vp['Duplex'];
}
if (isset($vp['PickTrayByPDFSize'])) {
if ($vp['PickTrayByPDFSize']) {
$out .= ' /PickTrayByPDFSize true';
} else {
$out .= ' /PickTrayByPDFSize false';
}
}
if (isset($vp['PrintPageRange'])) {
$PrintPageRangeNum = '';
foreach ($vp['PrintPageRange'] as $k => $v) {
$PrintPageRangeNum .= ' '.($v - 1).'';
}
$out .= ' /PrintPageRange ['.substr($PrintPageRangeNum,1).']';
}
if (isset($vp['NumCopies'])) {
$out .= ' /NumCopies '.intval($vp['NumCopies']);
}
$out .= ' >>';
return $out;
}
protected function _putheader() {
$this->_out('%PDF-'.$this->PDFVersion);
$this->_out('%'.chr(0xe2).chr(0xe3).chr(0xcf).chr(0xd3));
}
protected function _enddoc() {
if (isset($this->CurrentFont['fontkey']) AND isset($this->CurrentFont['subsetchars'])) {
$this->setFontSubBuffer($this->CurrentFont['fontkey'], 'subsetchars', $this->CurrentFont['subsetchars']);
}
$this->state = 1;
$this->_putheader();
$this->_putpages();
$this->_putresources();
if (!empty($this->empty_signature_appearance)) {
foreach ($this->empty_signature_appearance as $key => $esa) {
$out = $this->_getobj($esa['objid'])."\n";
$out .= '<< /Type /Annot';
$out .= ' /Subtype /Widget';
$out .= ' /Rect ['.$esa['rect'].']';
$out .= ' /P '.$this->page_obj_id[($esa['page'])].' 0 R';
$out .= ' /F 4';
$out .= ' /FT /Sig';
$signame = $esa['name'].sprintf(' [%03d]', ($key + 1));
$out .= ' /T '.$this->_textstring($signame, $esa['objid']);
$out .= ' /Ff 0';
$out .= ' >>';
$out .= "\n".'endobj';
$this->_out($out);
}
}
if ($this->sign AND isset($this->signature_data['cert_type'])) {
$out = $this->_getobj($this->sig_obj_id)."\n";
$out .= '<< /Type /Annot';
$out .= ' /Subtype /Widget';
$out .= ' /Rect ['.$this->signature_appearance['rect'].']';
$out .= ' /P '.$this->page_obj_id[($this->signature_appearance['page'])].' 0 R';
$out .= ' /F 4';
$out .= ' /FT /Sig';
$out .= ' /T '.$this->_textstring($this->signature_appearance['name'], $this->sig_obj_id);
$out .= ' /Ff 0';
$out .= ' /V '.($this->sig_obj_id + 1).' 0 R';
$out .= ' >>';
$out .= "\n".'endobj';
$this->_out($out);
$this->_putsignature();
}
$objid_info = $this->_putinfo();
$objid_catalog = $this->_putcatalog();
$o = $this->bufferlen;
$this->_out('xref');
$this->_out('0 '.($this->n + 1));
$this->_out('0000000000 65535 f ');
$freegen = ($this->n + 2);
for ($i=1; $i <= $this->n; ++$i) {
if (!isset($this->offsets[$i]) AND ($i > 1)) {
$this->_out(sprintf('0000000000 %05d f ', $freegen));
++$freegen;
} else {
$this->_out(sprintf('%010d 00000 n ', $this->offsets[$i]));
}
}
$out = 'trailer'."\n";
$out .= '<<';
$out .= ' /Size '.($this->n + 1);
$out .= ' /Root '.$objid_catalog.' 0 R';
$out .= ' /Info '.$objid_info.' 0 R';
if ($this->encrypted) {
$out .= ' /Encrypt '.$this->encryptdata['objid'].' 0 R';
}
$out .= ' /ID [ <'.$this->file_id.'> <'.$this->file_id.'> ]';
$out .= ' >>';
$this->_out($out);
$this->_out('startxref');
$this->_out($o);
$this->_out('%%EOF');
$this->state = 3;
}
protected function _beginpage($orientation='', $format='') {
++$this->page;
$this->pageobjects[$this->page] = array();
$this->setPageBuffer($this->page, '');
$this->transfmrk[$this->page] = array();
$this->state = 2;
if (TCPDF_STATIC::empty_string($orientation)) {
if (isset($this->CurOrientation)) {
$orientation = $this->CurOrientation;
} elseif ($this->fwPt > $this->fhPt) {
$orientation = 'L';
} else {
$orientation = 'P';
}
}
if (TCPDF_STATIC::empty_string($format)) {
$this->pagedim[$this->page] = $this->pagedim[($this->page - 1)];
$this->setPageOrientation($orientation);
} else {
$this->setPageFormat($format, $orientation);
}
if ($this->rtl) {
$this->x = $this->w - $this->rMargin;
} else {
$this->x = $this->lMargin;
}
$this->y = $this->tMargin;
if (isset($this->newpagegroup[$this->page])) {
$this->currpagegroup = $this->newpagegroup[$this->page];
$this->pagegroups[$this->currpagegroup] = 1;
} elseif (isset($this->currpagegroup) AND ($this->currpagegroup > 0)) {
++$this->pagegroups[$this->currpagegroup];
}
}
protected function _endpage() {
$this->setVisibility('all');
$this->state = 1;
}
protected function _newobj() {
$this->_out($this->_getobj());
return $this->n;
}
protected function _getobj($objid='') {
if ($objid === '') {
++$this->n;
$objid = $this->n;
}
$this->offsets[$objid] = $this->bufferlen;
$this->pageobjects[$this->page][] = $objid;
return $objid.' 0 obj';
}
protected function _dounderline($x, $y, $txt) {
$w = $this->GetStringWidth($txt);
return $this->_dounderlinew($x, $y, $w);
}
protected function _dounderlinew($x, $y, $w) {
$linew = - $this->CurrentFont['ut'] / 1000 * $this->FontSizePt;
return sprintf('%F %F %F %F re f', $x * $this->k, ((($this->h - $y) * $this->k) + $linew), $w * $this->k, $linew);
}
protected function _dolinethrough($x, $y, $txt) {
$w = $this->GetStringWidth($txt);
return $this->_dolinethroughw($x, $y, $w);
}
protected function _dolinethroughw($x, $y, $w) {
$linew = - $this->CurrentFont['ut'] / 1000 * $this->FontSizePt;
return sprintf('%F %F %F %F re f', $x * $this->k, ((($this->h - $y) * $this->k) + $linew + ($this->FontSizePt / 3)), $w * $this->k, $linew);
}
protected function _dooverline($x, $y, $txt) {
$w = $this->GetStringWidth($txt);
return $this->_dooverlinew($x, $y, $w);
}
protected function _dooverlinew($x, $y, $w) {
$linew = - $this->CurrentFont['ut'] / 1000 * $this->FontSizePt;
return sprintf('%F %F %F %F re f', $x * $this->k, (($this->h - $y + $this->FontAscent) * $this->k) - $linew, $w * $this->k, $linew);
}
protected function _datastring($s, $n=0) {
if ($n == 0) {
$n = $this->n;
}
$s = $this->_encrypt_data($n, $s);
return '('. TCPDF_STATIC::_escape($s).')';
}
public function setDocCreationTimestamp($time) {
if (is_string($time)) {
$time = TCPDF_STATIC::getTimestamp($time);
}
$this->doc_creation_timestamp = intval($time);
}
public function setDocModificationTimestamp($time) {
if (is_string($time)) {
$time = TCPDF_STATIC::getTimestamp($time);
}
$this->doc_modification_timestamp = intval($time);
}
public function getDocCreationTimestamp() {
return $this->doc_creation_timestamp;
}
public function getDocModificationTimestamp() {
return $this->doc_modification_timestamp;
}
protected function _datestring($n=0, $timestamp=0) {
if ((empty($timestamp)) OR ($timestamp < 0)) {
$timestamp = $this->doc_creation_timestamp;
}
return $this->_datastring('D:'.TCPDF_STATIC::getFormattedDate($timestamp), $n);
}
protected function _textstring($s, $n=0) {
if ($this->isunicode) {
$s = TCPDF_FONTS::UTF8ToUTF16BE($s, true, $this->isunicode, $this->CurrentFont);
}
return $this->_datastring($s, $n);
}
protected function _getrawstream($s, $n=0) {
if ($n <= 0) {
$n = $this->n;
}
return $this->_encrypt_data($n, $s);
}
protected function _out($s) {
if ($this->state == 2) {
if ($this->inxobj) {
$this->xobjects[$this->xobjid]['outdata'] .= $s."\n";
} elseif ((!$this->InFooter) AND isset($this->footerlen[$this->page]) AND ($this->footerlen[$this->page] > 0)) {
$pagebuff = $this->getPageBuffer($this->page);
$page = substr($pagebuff, 0, -$this->footerlen[$this->page]);
$footer = substr($pagebuff, -$this->footerlen[$this->page]);
$this->setPageBuffer($this->page, $page.$s."\n".$footer);
$this->footerpos[$this->page] += strlen($s."\n");
} else {
$this->setPageBuffer($this->page, $s."\n", true);
}
} elseif ($this->state > 0) {
$this->setBuffer($s."\n");
}
}
public function setHeaderFont($font) {
$this->header_font = $font;
}
public function getHeaderFont() {
return $this->header_font;
}
public function setFooterFont($font) {
$this->footer_font = $font;
}
public function getFooterFont() {
return $this->footer_font;
}
public function setLanguageArray($language) {
$this->l = $language;
if (isset($this->l['a_meta_dir'])) {
$this->rtl = $this->l['a_meta_dir']=='rtl' ? true : false;
} else {
$this->rtl = false;
}
}
public function getPDFData() {
if ($this->state < 3) {
$this->Close();
}
return $this->buffer;
}
public function addHtmlLink($url, $name, $fill=false, $firstline=false, $color='', $style=-1, $firstblock=false) {
if (isset($url[1]) AND ($url[0] == '#') AND is_numeric($url[1])) {
$lnkdata = explode(',', $url);
if (isset($lnkdata[0]) ) {
$page = substr($lnkdata[0], 1);
if (isset($lnkdata[1]) AND (strlen($lnkdata[1]) > 0)) {
$lnky = floatval($lnkdata[1]);
} else {
$lnky = 0;
}
$url = $this->AddLink();
$this->SetLink($url, $lnky, $page);
}
}
$prevcolor = $this->fgcolor;
$prevstyle = $this->FontStyle;
if (empty($color)) {
$this->SetTextColorArray($this->htmlLinkColorArray);
} else {
$this->SetTextColorArray($color);
}
if ($style == -1) {
$this->SetFont('', $this->FontStyle.$this->htmlLinkFontStyle);
} else {
$this->SetFont('', $this->FontStyle.$style);
}
$ret = $this->Write($this->lasth, $name, $url, $fill, '', false, 0, $firstline, $firstblock, 0);
$this->SetFont('', $prevstyle);
$this->SetTextColorArray($prevcolor);
return $ret;
}
public function pixelsToUnits($px) {
return ($px / ($this->imgscale * $this->k));
}
public function unhtmlentities($text_to_convert) {
return @html_entity_decode($text_to_convert, ENT_QUOTES, $this->encoding);
}
protected function _objectkey($n) {
$objkey = $this->encryptdata['key'].pack('VXxx', $n);
if ($this->encryptdata['mode'] == 2) {
$objkey .= "\x73\x41\x6C\x54";
}
$objkey = substr(TCPDF_STATIC::_md5_16($objkey), 0, (($this->encryptdata['Length'] / 8) + 5));
$objkey = substr($objkey, 0, 16);
return $objkey;
}
protected function _encrypt_data($n, $s) {
if (!$this->encrypted) {
return $s;
}
switch ($this->encryptdata['mode']) {
case 0:
case 1: {
$s = TCPDF_STATIC::_RC4($this->_objectkey($n), $s, $this->last_enc_key, $this->last_enc_key_c);
break;
}
case 2: {
$s = TCPDF_STATIC::_AES($this->_objectkey($n), $s);
break;
}
case 3: {
$s = TCPDF_STATIC::_AES($this->encryptdata['key'], $s);
break;
}
}
return $s;
}
protected function _putencryption() {
if (!$this->encrypted) {
return;
}
$this->encryptdata['objid'] = $this->_newobj();
$out = '<<';
if (!isset($this->encryptdata['Filter']) OR empty($this->encryptdata['Filter'])) {
$this->encryptdata['Filter'] = 'Standard';
}
$out .= ' /Filter /'.$this->encryptdata['Filter'];
if (isset($this->encryptdata['SubFilter']) AND !empty($this->encryptdata['SubFilter'])) {
$out .= ' /SubFilter /'.$this->encryptdata['SubFilter'];
}
if (!isset($this->encryptdata['V']) OR empty($this->encryptdata['V'])) {
$this->encryptdata['V'] = 1;
}
$out .= ' /V '.$this->encryptdata['V'];
if (isset($this->encryptdata['Length']) AND !empty($this->encryptdata['Length'])) {
$out .= ' /Length '.$this->encryptdata['Length'];
} else {
$out .= ' /Length 40';
}
if ($this->encryptdata['V'] >= 4) {
if (!isset($this->encryptdata['StmF']) OR empty($this->encryptdata['StmF'])) {
$this->encryptdata['StmF'] = 'Identity';
}
if (!isset($this->encryptdata['StrF']) OR empty($this->encryptdata['StrF'])) {
$this->encryptdata['StrF'] = 'Identity';
}
if (isset($this->encryptdata['CF']) AND !empty($this->encryptdata['CF'])) {
$out .= ' /CF <<';
$out .= ' /'.$this->encryptdata['StmF'].' <<';
$out .= ' /Type /CryptFilter';
if (isset($this->encryptdata['CF']['CFM']) AND !empty($this->encryptdata['CF']['CFM'])) {
$out .= ' /CFM /'.$this->encryptdata['CF']['CFM'];
if ($this->encryptdata['pubkey']) {
$out .= ' /Recipients [';
foreach ($this->encryptdata['Recipients'] as $rec) {
$out .= ' <'.$rec.'>';
}
$out .= ' ]';
if (isset($this->encryptdata['CF']['EncryptMetadata']) AND (!$this->encryptdata['CF']['EncryptMetadata'])) {
$out .= ' /EncryptMetadata false';
} else {
$out .= ' /EncryptMetadata true';
}
}
} else {
$out .= ' /CFM /None';
}
if (isset($this->encryptdata['CF']['AuthEvent']) AND !empty($this->encryptdata['CF']['AuthEvent'])) {
$out .= ' /AuthEvent /'.$this->encryptdata['CF']['AuthEvent'];
} else {
$out .= ' /AuthEvent /DocOpen';
}
if (isset($this->encryptdata['CF']['Length']) AND !empty($this->encryptdata['CF']['Length'])) {
$out .= ' /Length '.$this->encryptdata['CF']['Length'];
}
$out .= ' >> >>';
}
$out .= ' /StmF /'.$this->encryptdata['StmF'];
$out .= ' /StrF /'.$this->encryptdata['StrF'];
if (isset($this->encryptdata['EFF']) AND !empty($this->encryptdata['EFF'])) {
$out .= ' /EFF /'.$this->encryptdata[''];
}
}
if ($this->encryptdata['pubkey']) {
if (($this->encryptdata['V'] < 4) AND isset($this->encryptdata['Recipients']) AND !empty($this->encryptdata['Recipients'])) {
$out .= ' /Recipients [';
foreach ($this->encryptdata['Recipients'] as $rec) {
$out .= ' <'.$rec.'>';
}
$out .= ' ]';
}
} else {
$out .= ' /R';
if ($this->encryptdata['V'] == 5) {
$out .= ' 5';
$out .= ' /OE ('.TCPDF_STATIC::_escape($this->encryptdata['OE']).')';
$out .= ' /UE ('.TCPDF_STATIC::_escape($this->encryptdata['UE']).')';
$out .= ' /Perms ('.TCPDF_STATIC::_escape($this->encryptdata['perms']).')';
} elseif ($this->encryptdata['V'] == 4) {
$out .= ' 4';
} elseif ($this->encryptdata['V'] < 2) {
$out .= ' 2';
} else {
$out .= ' 3';
}
$out .= ' /O ('.TCPDF_STATIC::_escape($this->encryptdata['O']).')';
$out .= ' /U ('.TCPDF_STATIC::_escape($this->encryptdata['U']).')';
$out .= ' /P '.$this->encryptdata['P'];
if (isset($this->encryptdata['EncryptMetadata']) AND (!$this->encryptdata['EncryptMetadata'])) {
$out .= ' /EncryptMetadata false';
} else {
$out .= ' /EncryptMetadata true';
}
}
$out .= ' >>';
$out .= "\n".'endobj';
$this->_out($out);
}
protected function _Uvalue() {
if ($this->encryptdata['mode'] == 0) {
return TCPDF_STATIC::_RC4($this->encryptdata['key'], TCPDF_STATIC::$enc_padding, $this->last_enc_key, $this->last_enc_key_c);
} elseif ($this->encryptdata['mode'] < 3) {
$tmp = TCPDF_STATIC::_md5_16(TCPDF_STATIC::$enc_padding.$this->encryptdata['fileid']);
$enc = TCPDF_STATIC::_RC4($this->encryptdata['key'], $tmp, $this->last_enc_key, $this->last_enc_key_c);
$len = strlen($tmp);
for ($i = 1; $i <= 19; ++$i) {
$ek = '';
for ($j = 0; $j < $len; ++$j) {
$ek .= chr(ord($this->encryptdata['key'][$j]) ^ $i);
}
$enc = TCPDF_STATIC::_RC4($ek, $enc, $this->last_enc_key, $this->last_enc_key_c);
}
$enc .= str_repeat("\x00", 16);
return substr($enc, 0, 32);
} elseif ($this->encryptdata['mode'] == 3) {
$seed = TCPDF_STATIC::_md5_16(TCPDF_STATIC::getRandomSeed());
$this->encryptdata['UVS'] = substr($seed, 0, 8);
$this->encryptdata['UKS'] = substr($seed, 8, 16);
return hash('sha256', $this->encryptdata['user_password'].$this->encryptdata['UVS'], true).$this->encryptdata['UVS'].$this->encryptdata['UKS'];
}
}
protected function _UEvalue() {
$hashkey = hash('sha256', $this->encryptdata['user_password'].$this->encryptdata['UKS'], true);
return TCPDF_STATIC::_AESnopad($hashkey, $this->encryptdata['key']);
}
protected function _Ovalue() {
if ($this->encryptdata['mode'] < 3) {
$tmp = TCPDF_STATIC::_md5_16($this->encryptdata['owner_password']);
if ($this->encryptdata['mode'] > 0) {
for ($i = 0; $i < 50; ++$i) {
$tmp = TCPDF_STATIC::_md5_16($tmp);
}
}
$owner_key = substr($tmp, 0, ($this->encryptdata['Length'] / 8));
$enc = TCPDF_STATIC::_RC4($owner_key, $this->encryptdata['user_password'], $this->last_enc_key, $this->last_enc_key_c);
if ($this->encryptdata['mode'] > 0) {
$len = strlen($owner_key);
for ($i = 1; $i <= 19; ++$i) {
$ek = '';
for ($j = 0; $j < $len; ++$j) {
$ek .= chr(ord($owner_key[$j]) ^ $i);
}
$enc = TCPDF_STATIC::_RC4($ek, $enc, $this->last_enc_key, $this->last_enc_key_c);
}
}
return $enc;
} elseif ($this->encryptdata['mode'] == 3) {
$seed = TCPDF_STATIC::_md5_16(TCPDF_STATIC::getRandomSeed());
$this->encryptdata['OVS'] = substr($seed, 0, 8);
$this->encryptdata['OKS'] = substr($seed, 8, 16);
return hash('sha256', $this->encryptdata['owner_password'].$this->encryptdata['OVS'].$this->encryptdata['U'], true).$this->encryptdata['OVS'].$this->encryptdata['OKS'];
}
}
protected function _OEvalue() {
$hashkey = hash('sha256', $this->encryptdata['owner_password'].$this->encryptdata['OKS'].$this->encryptdata['U'], true);
return TCPDF_STATIC::_AESnopad($hashkey, $this->encryptdata['key']);
}
protected function _fixAES256Password($password) {
$psw = '';
$psw_array = TCPDF_FONTS::utf8Bidi(TCPDF_FONTS::UTF8StringToArray($password, $this->isunicode, $this->CurrentFont), $password, $this->rtl, $this->isunicode, $this->CurrentFont);
foreach ($psw_array as $c) {
$psw .= TCPDF_FONTS::unichr($c, $this->isunicode);
}
return substr($psw, 0, 127);
}
protected function _generateencryptionkey() {
$keybytelen = ($this->encryptdata['Length'] / 8);
if (!$this->encryptdata['pubkey']) {
if ($this->encryptdata['mode'] == 3) {
$this->encryptdata['key'] = substr(hash('sha256', TCPDF_STATIC::getRandomSeed(), true), 0, $keybytelen);
$this->encryptdata['user_password'] = $this->_fixAES256Password($this->encryptdata['user_password']);
$this->encryptdata['owner_password'] = $this->_fixAES256Password($this->encryptdata['owner_password']);
$this->encryptdata['U'] = $this->_Uvalue();
$this->encryptdata['UE'] = $this->_UEvalue();
$this->encryptdata['O'] = $this->_Ovalue();
$this->encryptdata['OE'] = $this->_OEvalue();
$this->encryptdata['P'] = $this->encryptdata['protection'];
$perms = TCPDF_STATIC::getEncPermissionsString($this->encryptdata['protection']);
$perms .= chr(255).chr(255).chr(255).chr(255);
if (isset($this->encryptdata['CF']['EncryptMetadata']) AND (!$this->encryptdata['CF']['EncryptMetadata'])) {
$perms .= 'F';
} else {
$perms .= 'T';
}
$perms .= 'adb';
$perms .= 'nick';
$this->encryptdata['perms'] = TCPDF_STATIC::_AESnopad($this->encryptdata['key'], $perms);
} else {
$this->encryptdata['user_password'] = substr($this->encryptdata['user_password'].TCPDF_STATIC::$enc_padding, 0, 32);
$this->encryptdata['owner_password'] = substr($this->encryptdata['owner_password'].TCPDF_STATIC::$enc_padding, 0, 32);
$this->encryptdata['O'] = $this->_Ovalue();
$permissions = TCPDF_STATIC::getEncPermissionsString($this->encryptdata['protection']);
$tmp = TCPDF_STATIC::_md5_16($this->encryptdata['user_password'].$this->encryptdata['O'].$permissions.$this->encryptdata['fileid']);
if ($this->encryptdata['mode'] > 0) {
for ($i = 0; $i < 50; ++$i) {
$tmp = TCPDF_STATIC::_md5_16(substr($tmp, 0, $keybytelen));
}
}
$this->encryptdata['key'] = substr($tmp, 0, $keybytelen);
$this->encryptdata['U'] = $this->_Uvalue();
$this->encryptdata['P'] = $this->encryptdata['protection'];
}
} else {
$seed = sha1(TCPDF_STATIC::getRandomSeed(), true);
$recipient_bytes = '';
foreach ($this->encryptdata['pubkeys'] as $pubkey) {
if (isset($pubkey['p'])) {
$pkprotection = TCPDF_STATIC::getUserPermissionCode($pubkey['p'], $this->encryptdata['mode']);
} else {
$pkprotection = $this->encryptdata['protection'];
}
$pkpermissions = TCPDF_STATIC::getEncPermissionsString($pkprotection);
$envelope = $seed.$pkpermissions;
$tempkeyfile = TCPDF_STATIC::getObjFilename('key', $this->file_id);
$f = TCPDF_STATIC::fopenLocal($tempkeyfile, 'wb');
if (!$f) {
$this->Error('Unable to create temporary key file: '.$tempkeyfile);
}
$envelope_length = strlen($envelope);
fwrite($f, $envelope, $envelope_length);
fclose($f);
$tempencfile = TCPDF_STATIC::getObjFilename('enc', $this->file_id);
if (!openssl_pkcs7_encrypt($tempkeyfile, $tempencfile, $pubkey['c'], array(), PKCS7_BINARY | PKCS7_DETACHED)) {
$this->Error('Unable to encrypt the file: '.$tempkeyfile);
}
$signature = file_get_contents($tempencfile, false, null, $envelope_length);
$signature = substr($signature, strpos($signature, 'Content-Disposition'));
$tmparr = explode("\n\n", $signature);
$signature = trim($tmparr[1]);
unset($tmparr);
$signature = base64_decode($signature);
$hexsignature = current(unpack('H*', $signature));
$this->encryptdata['Recipients'][] = $hexsignature;
$recipient_bytes .= $signature;
}
if ($this->encryptdata['mode'] == 3) {
$this->encryptdata['key'] = substr(hash('sha256', $seed.$recipient_bytes, true), 0, $keybytelen);
} else {
$this->encryptdata['key'] = substr(sha1($seed.$recipient_bytes, true), 0, $keybytelen);
}
}
}
public function SetProtection($permissions=array('print', 'modify', 'copy', 'annot-forms', 'fill-forms', 'extract', 'assemble', 'print-high'), $user_pass='', $owner_pass=null, $mode=0, $pubkeys=null) {
if ($this->pdfa_mode) {
return;
}
$this->encryptdata['protection'] = TCPDF_STATIC::getUserPermissionCode($permissions, $mode);
if (($pubkeys !== null) AND (is_array($pubkeys))) {
$this->encryptdata['pubkeys'] = $pubkeys;
if ($mode == 0) {
$mode = 1;
}
if (!function_exists('openssl_pkcs7_encrypt')) {
$this->Error('Public-Key Security requires openssl library.');
}
$this->encryptdata['pubkey'] = true;
$this->encryptdata['Filter'] = 'Adobe.PubSec';
$this->encryptdata['StmF'] = 'DefaultCryptFilter';
$this->encryptdata['StrF'] = 'DefaultCryptFilter';
} else {
$this->encryptdata['pubkey'] = false;
$this->encryptdata['Filter'] = 'Standard';
$this->encryptdata['StmF'] = 'StdCF';
$this->encryptdata['StrF'] = 'StdCF';
}
if ($mode > 1) {
if (!extension_loaded('openssl') && !extension_loaded('mcrypt')) {
$this->Error('AES encryption requires openssl or mcrypt extension (http://www.php.net/manual/en/mcrypt.requirements.php).');
}
if (extension_loaded('openssl') && !in_array('aes-256-cbc', openssl_get_cipher_methods())) {
$this->Error('AES encryption requires openssl/aes-256-cbc cypher.');
}
if (extension_loaded('mcrypt') && mcrypt_get_cipher_name(MCRYPT_RIJNDAEL_128) === false) {
$this->Error('AES encryption requires MCRYPT_RIJNDAEL_128 cypher.');
}
if (($mode == 3) AND !function_exists('hash')) {
$this->Error('AES 256 encryption requires HASH Message Digest Framework (http://www.php.net/manual/en/book.hash.php).');
}
}
if ($owner_pass === null) {
$owner_pass = md5(TCPDF_STATIC::getRandomSeed());
}
$this->encryptdata['user_password'] = $user_pass;
$this->encryptdata['owner_password'] = $owner_pass;
$this->encryptdata['mode'] = $mode;
switch ($mode) {
case 0: {
$this->encryptdata['V'] = 1;
$this->encryptdata['Length'] = 40;
$this->encryptdata['CF']['CFM'] = 'V2';
break;
}
case 1: {
$this->encryptdata['V'] = 2;
$this->encryptdata['Length'] = 128;
$this->encryptdata['CF']['CFM'] = 'V2';
if ($this->encryptdata['pubkey']) {
$this->encryptdata['SubFilter'] = 'adbe.pkcs7.s4';
$this->encryptdata['Recipients'] = array();
}
break;
}
case 2: {
$this->encryptdata['V'] = 4;
$this->encryptdata['Length'] = 128;
$this->encryptdata['CF']['CFM'] = 'AESV2';
$this->encryptdata['CF']['Length'] = 128;
if ($this->encryptdata['pubkey']) {
$this->encryptdata['SubFilter'] = 'adbe.pkcs7.s5';
$this->encryptdata['Recipients'] = array();
}
break;
}
case 3: {
$this->encryptdata['V'] = 5;
$this->encryptdata['Length'] = 256;
$this->encryptdata['CF']['CFM'] = 'AESV3';
$this->encryptdata['CF']['Length'] = 256;
if ($this->encryptdata['pubkey']) {
$this->encryptdata['SubFilter'] = 'adbe.pkcs7.s5';
$this->encryptdata['Recipients'] = array();
}
break;
}
}
$this->encrypted = true;
$this->encryptdata['fileid'] = TCPDF_STATIC::convertHexStringToString($this->file_id);
$this->_generateencryptionkey();
}
public function StartTransform() {
if ($this->state != 2) {
return;
}
$this->_outSaveGraphicsState();
if ($this->inxobj) {
$this->xobjects[$this->xobjid]['transfmrk'][] = strlen($this->xobjects[$this->xobjid]['outdata']);
} else {
$this->transfmrk[$this->page][] = $this->pagelen[$this->page];
}
++$this->transfmatrix_key;
$this->transfmatrix[$this->transfmatrix_key] = array();
}
public function StopTransform() {
if ($this->state != 2) {
return;
}
$this->_outRestoreGraphicsState();
if (isset($this->transfmatrix[$this->transfmatrix_key])) {
array_pop($this->transfmatrix[$this->transfmatrix_key]);
--$this->transfmatrix_key;
}
if ($this->inxobj) {
array_pop($this->xobjects[$this->xobjid]['transfmrk']);
} else {
array_pop($this->transfmrk[$this->page]);
}
}
public function ScaleX($s_x, $x='', $y='') {
$this->Scale($s_x, 100, $x, $y);
}
public function ScaleY($s_y, $x='', $y='') {
$this->Scale(100, $s_y, $x, $y);
}
public function ScaleXY($s, $x='', $y='') {
$this->Scale($s, $s, $x, $y);
}
public function Scale($s_x, $s_y, $x='', $y='') {
if ($x === '') {
$x = $this->x;
}
if ($y === '') {
$y = $this->y;
}
if (($s_x == 0) OR ($s_y == 0)) {
$this->Error('Please do not use values equal to zero for scaling');
}
$y = ($this->h - $y) * $this->k;
$x *= $this->k;
$s_x /= 100;
$s_y /= 100;
$tm = array();
$tm[0] = $s_x;
$tm[1] = 0;
$tm[2] = 0;
$tm[3] = $s_y;
$tm[4] = $x * (1 - $s_x);
$tm[5] = $y * (1 - $s_y);
$this->Transform($tm);
}
public function MirrorH($x='') {
$this->Scale(-100, 100, $x);
}
public function MirrorV($y='') {
$this->Scale(100, -100, '', $y);
}
public function MirrorP($x='',$y='') {
$this->Scale(-100, -100, $x, $y);
}
public function MirrorL($angle=0, $x='',$y='') {
$this->Scale(-100, 100, $x, $y);
$this->Rotate(-2*($angle-90), $x, $y);
}
public function TranslateX($t_x) {
$this->Translate($t_x, 0);
}
public function TranslateY($t_y) {
$this->Translate(0, $t_y);
}
public function Translate($t_x, $t_y) {
$tm = array();
$tm[0] = 1;
$tm[1] = 0;
$tm[2] = 0;
$tm[3] = 1;
$tm[4] = $t_x * $this->k;
$tm[5] = -$t_y * $this->k;
$this->Transform($tm);
}
public function Rotate($angle, $x='', $y='') {
if ($x === '') {
$x = $this->x;
}
if ($y === '') {
$y = $this->y;
}
$y = ($this->h - $y) * $this->k;
$x *= $this->k;
$tm = array();
$tm[0] = cos(deg2rad($angle));
$tm[1] = sin(deg2rad($angle));
$tm[2] = -$tm[1];
$tm[3] = $tm[0];
$tm[4] = $x + ($tm[1] * $y) - ($tm[0] * $x);
$tm[5] = $y - ($tm[0] * $y) - ($tm[1] * $x);
$this->Transform($tm);
}
public function SkewX($angle_x, $x='', $y='') {
$this->Skew($angle_x, 0, $x, $y);
}
public function SkewY($angle_y, $x='', $y='') {
$this->Skew(0, $angle_y, $x, $y);
}
public function Skew($angle_x, $angle_y, $x='', $y='') {
if ($x === '') {
$x = $this->x;
}
if ($y === '') {
$y = $this->y;
}
if (($angle_x <= -90) OR ($angle_x >= 90) OR ($angle_y <= -90) OR ($angle_y >= 90)) {
$this->Error('Please use values between -90 and +90 degrees for Skewing.');
}
$x *= $this->k;
$y = ($this->h - $y) * $this->k;
$tm = array();
$tm[0] = 1;
$tm[1] = tan(deg2rad($angle_y));
$tm[2] = tan(deg2rad($angle_x));
$tm[3] = 1;
$tm[4] = -$tm[2] * $y;
$tm[5] = -$tm[1] * $x;
$this->Transform($tm);
}
protected function Transform($tm) {
if ($this->state != 2) {
return;
}
$this->_out(sprintf('%F %F %F %F %F %F cm', $tm[0], $tm[1], $tm[2], $tm[3], $tm[4], $tm[5]));
$this->transfmatrix[$this->transfmatrix_key][] = array('a' => $tm[0], 'b' => $tm[1], 'c' => $tm[2], 'd' => $tm[3], 'e' => $tm[4], 'f' => $tm[5]);
if ($this->inxobj) {
if (end($this->xobjects[$this->xobjid]['transfmrk']) !== false) {
$key = key($this->xobjects[$this->xobjid]['transfmrk']);
$this->xobjects[$this->xobjid]['transfmrk'][$key] = strlen($this->xobjects[$this->xobjid]['outdata']);
}
} elseif (end($this->transfmrk[$this->page]) !== false) {
$key = key($this->transfmrk[$this->page]);
$this->transfmrk[$this->page][$key] = $this->pagelen[$this->page];
}
}
public function SetLineWidth($width) {
$this->LineWidth = $width;
$this->linestyleWidth = sprintf('%F w', ($width * $this->k));
if ($this->state == 2) {
$this->_out($this->linestyleWidth);
}
}
public function GetLineWidth() {
return $this->LineWidth;
}
public function SetLineStyle($style, $ret=false) {
$s = '';
if (!is_array($style)) {
return;
}
if (isset($style['width'])) {
$this->LineWidth = $style['width'];
$this->linestyleWidth = sprintf('%F w', ($style['width'] * $this->k));
$s .= $this->linestyleWidth.' ';
}
if (isset($style['cap'])) {
$ca = array('butt' => 0, 'round'=> 1, 'square' => 2);
if (isset($ca[$style['cap']])) {
$this->linestyleCap = $ca[$style['cap']].' J';
$s .= $this->linestyleCap.' ';
}
}
if (isset($style['join'])) {
$ja = array('miter' => 0, 'round' => 1, 'bevel' => 2);
if (isset($ja[$style['join']])) {
$this->linestyleJoin = $ja[$style['join']].' j';
$s .= $this->linestyleJoin.' ';
}
}
if (isset($style['dash'])) {
$dash_string = '';
if ($style['dash']) {
if (preg_match('/^.+,/', $style['dash']) > 0) {
$tab = explode(',', $style['dash']);
} else {
$tab = array($style['dash']);
}
$dash_string = '';
foreach ($tab as $i => $v) {
if ($i) {
$dash_string .= ' ';
}
$dash_string .= sprintf('%F', $v);
}
}
if (!isset($style['phase']) OR !$style['dash']) {
$style['phase'] = 0;
}
$this->linestyleDash = sprintf('[%s] %F d', $dash_string, $style['phase']);
$s .= $this->linestyleDash.' ';
}
if (isset($style['color'])) {
$s .= $this->SetDrawColorArray($style['color'], true).' ';
}
if (!$ret AND ($this->state == 2)) {
$this->_out($s);
}
return $s;
}
protected function _outPoint($x, $y) {
if ($this->state == 2) {
$this->_out(sprintf('%F %F m', ($x * $this->k), (($this->h - $y) * $this->k)));
}
}
protected function _outLine($x, $y) {
if ($this->state == 2) {
$this->_out(sprintf('%F %F l', ($x * $this->k), (($this->h - $y) * $this->k)));
}
}
protected function _outRect($x, $y, $w, $h, $op) {
if ($this->state == 2) {
$this->_out(sprintf('%F %F %F %F re %s', ($x * $this->k), (($this->h - $y) * $this->k), ($w * $this->k), (-$h * $this->k), $op));
}
}
protected function _outCurve($x1, $y1, $x2, $y2, $x3, $y3) {
if ($this->state == 2) {
$this->_out(sprintf('%F %F %F %F %F %F c', ($x1 * $this->k), (($this->h - $y1) * $this->k), ($x2 * $this->k), (($this->h - $y2) * $this->k), ($x3 * $this->k), (($this->h - $y3) * $this->k)));
}
}
protected function _outCurveV($x2, $y2, $x3, $y3) {
if ($this->state == 2) {
$this->_out(sprintf('%F %F %F %F v', ($x2 * $this->k), (($this->h - $y2) * $this->k), ($x3 * $this->k), (($this->h - $y3) * $this->k)));
}
}
protected function _outCurveY($x1, $y1, $x3, $y3) {
if ($this->state == 2) {
$this->_out(sprintf('%F %F %F %F y', ($x1 * $this->k), (($this->h - $y1) * $this->k), ($x3 * $this->k), (($this->h - $y3) * $this->k)));
}
}
public function Line($x1, $y1, $x2, $y2, $style=array()) {
if ($this->state != 2) {
return;
}
if (is_array($style)) {
$this->SetLineStyle($style);
}
$this->_outPoint($x1, $y1);
$this->_outLine($x2, $y2);
$this->_out('S');
}
public function Rect($x, $y, $w, $h, $style='', $border_style=array(), $fill_color=array()) {
if ($this->state != 2) {
return;
}
if (empty($style)) {
$style = 'S';
}
if (!(strpos($style, 'F') === false) AND !empty($fill_color)) {
$this->SetFillColorArray($fill_color);
}
if (!empty($border_style)) {
if (isset($border_style['all']) AND !empty($border_style['all'])) {
$this->SetLineStyle($border_style['all']);
$border_style = array();
} else {
$opnostroke = array('S' => '', 'D' => '', 's' => '', 'd' => '', 'B' => 'F', 'FD' => 'F', 'DF' => 'F', 'B*' => 'F*', 'F*D' => 'F*', 'DF*' => 'F*', 'b' => 'f', 'fd' => 'f', 'df' => 'f', 'b*' => 'f*', 'f*d' => 'f*', 'df*' => 'f*' );
if (isset($opnostroke[$style])) {
$style = $opnostroke[$style];
}
}
}
if (!empty($style)) {
$op = TCPDF_STATIC::getPathPaintOperator($style);
$this->_outRect($x, $y, $w, $h, $op);
}
if (!empty($border_style)) {
$border_style2 = array();
foreach ($border_style as $line => $value) {
$length = strlen($line);
for ($i = 0; $i < $length; ++$i) {
$border_style2[$line[$i]] = $value;
}
}
$border_style = $border_style2;
if (isset($border_style['L']) AND $border_style['L']) {
$this->Line($x, $y, $x, $y + $h, $border_style['L']);
}
if (isset($border_style['T']) AND $border_style['T']) {
$this->Line($x, $y, $x + $w, $y, $border_style['T']);
}
if (isset($border_style['R']) AND $border_style['R']) {
$this->Line($x + $w, $y, $x + $w, $y + $h, $border_style['R']);
}
if (isset($border_style['B']) AND $border_style['B']) {
$this->Line($x, $y + $h, $x + $w, $y + $h, $border_style['B']);
}
}
}
public function Curve($x0, $y0, $x1, $y1, $x2, $y2, $x3, $y3, $style='', $line_style=array(), $fill_color=array()) {
if ($this->state != 2) {
return;
}
if (!(false === strpos($style, 'F')) AND isset($fill_color)) {
$this->SetFillColorArray($fill_color);
}
$op = TCPDF_STATIC::getPathPaintOperator($style);
if ($line_style) {
$this->SetLineStyle($line_style);
}
$this->_outPoint($x0, $y0);
$this->_outCurve($x1, $y1, $x2, $y2, $x3, $y3);
$this->_out($op);
}
public function Polycurve($x0, $y0, $segments, $style='', $line_style=array(), $fill_color=array()) {
if ($this->state != 2) {
return;
}
if (!(false === strpos($style, 'F')) AND isset($fill_color)) {
$this->SetFillColorArray($fill_color);
}
$op = TCPDF_STATIC::getPathPaintOperator($style);
if ($op == 'f') {
$line_style = array();
}
if ($line_style) {
$this->SetLineStyle($line_style);
}
$this->_outPoint($x0, $y0);
foreach ($segments as $segment) {
list($x1, $y1, $x2, $y2, $x3, $y3) = $segment;
$this->_outCurve($x1, $y1, $x2, $y2, $x3, $y3);
}
$this->_out($op);
}
public function Ellipse($x0, $y0, $rx, $ry='', $angle=0, $astart=0, $afinish=360, $style='', $line_style=array(), $fill_color=array(), $nc=2) {
if ($this->state != 2) {
return;
}
if (TCPDF_STATIC::empty_string($ry) OR ($ry == 0)) {
$ry = $rx;
}
if (!(false === strpos($style, 'F')) AND isset($fill_color)) {
$this->SetFillColorArray($fill_color);
}
$op = TCPDF_STATIC::getPathPaintOperator($style);
if ($op == 'f') {
$line_style = array();
}
if ($line_style) {
$this->SetLineStyle($line_style);
}
$this->_outellipticalarc($x0, $y0, $rx, $ry, $angle, $astart, $afinish, false, $nc, true, true, false);
$this->_out($op);
}
protected function _outellipticalarc($xc, $yc, $rx, $ry, $xang=0, $angs=0, $angf=360, $pie=false, $nc=2, $startpoint=true, $ccw=true, $svg=false) {
if (($rx <= 0) OR ($ry < 0)) {
return;
}
$k = $this->k;
if ($nc < 2) {
$nc = 2;
}
$xmin = 2147483647;
$ymin = 2147483647;
$xmax = 0;
$ymax = 0;
if ($pie) {
$this->_outPoint($xc, $yc);
}
$xang = deg2rad((float) $xang);
$angs = deg2rad((float) $angs);
$angf = deg2rad((float) $angf);
if ($svg) {
$as = $angs;
$af = $angf;
} else {
$as = atan2((sin($angs) / $ry), (cos($angs) / $rx));
$af = atan2((sin($angf) / $ry), (cos($angf) / $rx));
}
if ($as < 0) {
$as += (2 * M_PI);
}
if ($af < 0) {
$af += (2 * M_PI);
}
if ($ccw AND ($as > $af)) {
$as -= (2 * M_PI);
} elseif (!$ccw AND ($as < $af)) {
$af -= (2 * M_PI);
}
$total_angle = ($af - $as);
if ($nc < 2) {
$nc = 2;
}
$nc *= (2 * abs($total_angle) / M_PI);
$nc = round($nc) + 1;
$arcang = ($total_angle / $nc);
$x0 = $xc;
$y0 = ($this->h - $yc);
$ang = $as;
$alpha = sin($arcang) * ((sqrt(4 + (3 * pow(tan(($arcang) / 2), 2))) - 1) / 3);
$cos_xang = cos($xang);
$sin_xang = sin($xang);
$cos_ang = cos($ang);
$sin_ang = sin($ang);
$px1 = $x0 + ($rx * $cos_xang * $cos_ang) - ($ry * $sin_xang * $sin_ang);
$py1 = $y0 + ($rx * $sin_xang * $cos_ang) + ($ry * $cos_xang * $sin_ang);
$qx1 = ($alpha * ((-$rx * $cos_xang * $sin_ang) - ($ry * $sin_xang * $cos_ang)));
$qy1 = ($alpha * ((-$rx * $sin_xang * $sin_ang) + ($ry * $cos_xang * $cos_ang)));
if ($pie) {
$this->_outLine($px1, $this->h - $py1);
} elseif ($startpoint) {
$this->_outPoint($px1, $this->h - $py1);
}
for ($i = 1; $i <= $nc; ++$i) {
$ang = $as + ($i * $arcang);
if ($i == $nc) {
$ang = $af;
}
$cos_ang = cos($ang);
$sin_ang = sin($ang);
$px2 = $x0 + ($rx * $cos_xang * $cos_ang) - ($ry * $sin_xang * $sin_ang);
$py2 = $y0 + ($rx * $sin_xang * $cos_ang) + ($ry * $cos_xang * $sin_ang);
$qx2 = ($alpha * ((-$rx * $cos_xang * $sin_ang) - ($ry * $sin_xang * $cos_ang)));
$qy2 = ($alpha * ((-$rx * $sin_xang * $sin_ang) + ($ry * $cos_xang * $cos_ang)));
$cx1 = ($px1 + $qx1);
$cy1 = ($this->h - ($py1 + $qy1));
$cx2 = ($px2 - $qx2);
$cy2 = ($this->h - ($py2 - $qy2));
$cx3 = $px2;
$cy3 = ($this->h - $py2);
$this->_outCurve($cx1, $cy1, $cx2, $cy2, $cx3, $cy3);
$xmin = min($xmin, $cx1, $cx2, $cx3);
$ymin = min($ymin, $cy1, $cy2, $cy3);
$xmax = max($xmax, $cx1, $cx2, $cx3);
$ymax = max($ymax, $cy1, $cy2, $cy3);
$px1 = $px2;
$py1 = $py2;
$qx1 = $qx2;
$qy1 = $qy2;
}
if ($pie) {
$this->_outLine($xc, $yc);
$xmin = min($xmin, $xc);
$ymin = min($ymin, $yc);
$xmax = max($xmax, $xc);
$ymax = max($ymax, $yc);
}
return array($xmin, $ymin, $xmax, $ymax);
}
public function Circle($x0, $y0, $r, $angstr=0, $angend=360, $style='', $line_style=array(), $fill_color=array(), $nc=2) {
$this->Ellipse($x0, $y0, $r, $r, 0, $angstr, $angend, $style, $line_style, $fill_color, $nc);
}
public function PolyLine($p, $style='', $line_style=array(), $fill_color=array()) {
$this->Polygon($p, $style, $line_style, $fill_color, false);
}
public function Polygon($p, $style='', $line_style=array(), $fill_color=array(), $closed=true) {
if ($this->state != 2) {
return;
}
$nc = count($p);
$np = $nc / 2;
if ($closed) {
for ($i = 0; $i < 4; ++$i) {
$p[$nc + $i] = $p[$i];
}
if (isset($line_style[0])) {
$line_style[$np] = $line_style[0];
}
$nc += 4;
}
if (!(false === strpos($style, 'F')) AND isset($fill_color)) {
$this->SetFillColorArray($fill_color);
}
$op = TCPDF_STATIC::getPathPaintOperator($style);
if ($op == 'f') {
$line_style = array();
}
$draw = true;
if ($line_style) {
if (isset($line_style['all'])) {
$this->SetLineStyle($line_style['all']);
} else {
$draw = false;
if ($op == 'B') {
$op = 'f';
$this->_outPoint($p[0], $p[1]);
for ($i = 2; $i < $nc; $i = $i + 2) {
$this->_outLine($p[$i], $p[$i + 1]);
}
$this->_out($op);
}
$this->_outPoint($p[0], $p[1]);
for ($i = 2; $i < $nc; $i = $i + 2) {
$line_num = ($i / 2) - 1;
if (isset($line_style[$line_num])) {
if ($line_style[$line_num] != 0) {
if (is_array($line_style[$line_num])) {
$this->_out('S');
$this->SetLineStyle($line_style[$line_num]);
$this->_outPoint($p[$i - 2], $p[$i - 1]);
$this->_outLine($p[$i], $p[$i + 1]);
$this->_out('S');
$this->_outPoint($p[$i], $p[$i + 1]);
} else {
$this->_outLine($p[$i], $p[$i + 1]);
}
}
} else {
$this->_outLine($p[$i], $p[$i + 1]);
}
}
$this->_out($op);
}
}
if ($draw) {
$this->_outPoint($p[0], $p[1]);
for ($i = 2; $i < $nc; $i = $i + 2) {
$this->_outLine($p[$i], $p[$i + 1]);
}
$this->_out($op);
}
}
public function RegularPolygon($x0, $y0, $r, $ns, $angle=0, $draw_circle=false, $style='', $line_style=array(), $fill_color=array(), $circle_style='', $circle_outLine_style=array(), $circle_fill_color=array()) {
if (3 > $ns) {
$ns = 3;
}
if ($draw_circle) {
$this->Circle($x0, $y0, $r, 0, 360, $circle_style, $circle_outLine_style, $circle_fill_color);
}
$p = array();
for ($i = 0; $i < $ns; ++$i) {
$a = $angle + ($i * 360 / $ns);
$a_rad = deg2rad((float) $a);
$p[] = $x0 + ($r * sin($a_rad));
$p[] = $y0 + ($r * cos($a_rad));
}
$this->Polygon($p, $style, $line_style, $fill_color);
}
public function StarPolygon($x0, $y0, $r, $nv, $ng, $angle=0, $draw_circle=false, $style='', $line_style=array(), $fill_color=array(), $circle_style='', $circle_outLine_style=array(), $circle_fill_color=array()) {
if ($nv < 2) {
$nv = 2;
}
if ($draw_circle) {
$this->Circle($x0, $y0, $r, 0, 360, $circle_style, $circle_outLine_style, $circle_fill_color);
}
$p2 = array();
$visited = array();
for ($i = 0; $i < $nv; ++$i) {
$a = $angle + ($i * 360 / $nv);
$a_rad = deg2rad((float) $a);
$p2[] = $x0 + ($r * sin($a_rad));
$p2[] = $y0 + ($r * cos($a_rad));
$visited[] = false;
}
$p = array();
$i = 0;
do {
$p[] = $p2[$i * 2];
$p[] = $p2[($i * 2) + 1];
$visited[$i] = true;
$i += $ng;
$i %= $nv;
} while (!$visited[$i]);
$this->Polygon($p, $style, $line_style, $fill_color);
}
public function RoundedRect($x, $y, $w, $h, $r, $round_corner='1111', $style='', $border_style=array(), $fill_color=array()) {
$this->RoundedRectXY($x, $y, $w, $h, $r, $r, $round_corner, $style, $border_style, $fill_color);
}
public function RoundedRectXY($x, $y, $w, $h, $rx, $ry, $round_corner='1111', $style='', $border_style=array(), $fill_color=array()) {
if ($this->state != 2) {
return;
}
if (($round_corner == '0000') OR (($rx == $ry) AND ($rx == 0))) {
$this->Rect($x, $y, $w, $h, $style, $border_style, $fill_color);
return;
}
if (!(false === strpos($style, 'F')) AND isset($fill_color)) {
$this->SetFillColorArray($fill_color);
}
$op = TCPDF_STATIC::getPathPaintOperator($style);
if ($op == 'f') {
$border_style = array();
}
if ($border_style) {
$this->SetLineStyle($border_style);
}
$MyArc = 4 / 3 * (sqrt(2) - 1);
$this->_outPoint($x + $rx, $y);
$xc = $x + $w - $rx;
$yc = $y + $ry;
$this->_outLine($xc, $y);
if ($round_corner[0]) {
$this->_outCurve($xc + ($rx * $MyArc), $yc - $ry, $xc + $rx, $yc - ($ry * $MyArc), $xc + $rx, $yc);
} else {
$this->_outLine($x + $w, $y);
}
$xc = $x + $w - $rx;
$yc = $y + $h - $ry;
$this->_outLine($x + $w, $yc);
if ($round_corner[1]) {
$this->_outCurve($xc + $rx, $yc + ($ry * $MyArc), $xc + ($rx * $MyArc), $yc + $ry, $xc, $yc + $ry);
} else {
$this->_outLine($x + $w, $y + $h);
}
$xc = $x + $rx;
$yc = $y + $h - $ry;
$this->_outLine($xc, $y + $h);
if ($round_corner[2]) {
$this->_outCurve($xc - ($rx * $MyArc), $yc + $ry, $xc - $rx, $yc + ($ry * $MyArc), $xc - $rx, $yc);
} else {
$this->_outLine($x, $y + $h);
}
$xc = $x + $rx;
$yc = $y + $ry;
$this->_outLine($x, $yc);
if ($round_corner[3]) {
$this->_outCurve($xc - $rx, $yc - ($ry * $MyArc), $xc - ($rx * $MyArc), $yc - $ry, $xc, $yc - $ry);
} else {
$this->_outLine($x, $y);
$this->_outLine($x + $rx, $y);
}
$this->_out($op);
}
public function Arrow($x0, $y0, $x1, $y1, $head_style=0, $arm_size=5, $arm_angle=15) {
$dir_angle = atan2(($y0 - $y1), ($x0 - $x1));
if ($dir_angle < 0) {
$dir_angle += (2 * M_PI);
}
$arm_angle = deg2rad($arm_angle);
$sx1 = $x1;
$sy1 = $y1;
if ($head_style > 0) {
$sx1 = $x1 + (($arm_size - $this->LineWidth) * cos($dir_angle));
$sy1 = $y1 + (($arm_size - $this->LineWidth) * sin($dir_angle));
}
$this->Line($x0, $y0, $sx1, $sy1);
$x2L = $x1 + ($arm_size * cos($dir_angle + $arm_angle));
$y2L = $y1 + ($arm_size * sin($dir_angle + $arm_angle));
$x2R = $x1 + ($arm_size * cos($dir_angle - $arm_angle));
$y2R = $y1 + ($arm_size * sin($dir_angle - $arm_angle));
$mode = 'D';
$style = array();
switch ($head_style) {
case 0: {
$mode = 'D';
$style = array(1, 1, 0);
break;
}
case 1: {
$mode = 'D';
break;
}
case 2: {
$mode = 'DF';
break;
}
case 3: {
$mode = 'F';
break;
}
}
$this->Polygon(array($x2L, $y2L, $x1, $y1, $x2R, $y2R), $mode, $style, array());
}
public function setDestination($name, $y=-1, $page='', $x=-1) {
$name = TCPDF_STATIC::encodeNameObject($name);
if (TCPDF_STATIC::empty_string($name)) {
return false;
}
if ($y == -1) {
$y = $this->GetY();
} elseif ($y < 0) {
$y = 0;
} elseif ($y > $this->h) {
$y = $this->h;
}
if ($x == -1) {
$x = $this->GetX();
} elseif ($x < 0) {
$x = 0;
} elseif ($x > $this->w) {
$x = $this->w;
}
$fixed = false;
if (!empty($page) AND ($page[0] == '*')) {
$page = intval(substr($page, 1));
$fixed = true;
}
if (empty($page)) {
$page = $this->PageNo();
if (empty($page)) {
return;
}
}
$this->dests[$name] = array('x' => $x, 'y' => $y, 'p' => $page, 'f' => $fixed);
return $name;
}
public function getDestination() {
return $this->dests;
}
protected function _putdests() {
if (empty($this->dests)) {
return;
}
$this->n_dests = $this->_newobj();
$out = ' <<';
foreach($this->dests as $name => $o) {
$out .= ' /'.$name.' '.sprintf('[%u 0 R /XYZ %F %F null]', $this->page_obj_id[($o['p'])], ($o['x'] * $this->k), ($this->pagedim[$o['p']]['h'] - ($o['y'] * $this->k)));
}
$out .= ' >>';
$out .= "\n".'endobj';
$this->_out($out);
}
public function setBookmark($txt, $level=0, $y=-1, $page='', $style='', $color=array(0,0,0), $x=-1, $link='') {
$this->Bookmark($txt, $level, $y, $page, $style, $color, $x, $link);
}
public function Bookmark($txt, $level=0, $y=-1, $page='', $style='', $color=array(0,0,0), $x=-1, $link='') {
if ($level < 0) {
$level = 0;
}
if (isset($this->outlines[0])) {
$lastoutline = end($this->outlines);
$maxlevel = $lastoutline['l'] + 1;
} else {
$maxlevel = 0;
}
if ($level > $maxlevel) {
$level = $maxlevel;
}
if ($y == -1) {
$y = $this->GetY();
} elseif ($y < 0) {
$y = 0;
} elseif ($y > $this->h) {
$y = $this->h;
}
if ($x == -1) {
$x = $this->GetX();
} elseif ($x < 0) {
$x = 0;
} elseif ($x > $this->w) {
$x = $this->w;
}
$fixed = false;
if (!empty($page) AND ($page[0] == '*')) {
$page = intval(substr($page, 1));
$fixed = true;
}
if (empty($page)) {
$page = $this->PageNo();
if (empty($page)) {
return;
}
}
$this->outlines[] = array('t' => $txt, 'l' => $level, 'x' => $x, 'y' => $y, 'p' => $page, 'f' => $fixed, 's' => strtoupper($style), 'c' => $color, 'u' => $link);
}
protected function sortBookmarks() {
$outline_p = array();
$outline_y = array();
foreach ($this->outlines as $key => $row) {
$outline_p[$key] = $row['p'];
$outline_k[$key] = $key;
}
array_multisort($outline_p, SORT_NUMERIC, SORT_ASC, $outline_k, SORT_NUMERIC, SORT_ASC, $this->outlines);
}
protected function _putbookmarks() {
$nb = count($this->outlines);
if ($nb == 0) {
return;
}
$this->sortBookmarks();
$lru = array();
$level = 0;
foreach ($this->outlines as $i => $o) {
if ($o['l'] > 0) {
$parent = $lru[($o['l'] - 1)];
$this->outlines[$i]['parent'] = $parent;
$this->outlines[$parent]['last'] = $i;
if ($o['l'] > $level) {
$this->outlines[$parent]['first'] = $i;
}
} else {
$this->outlines[$i]['parent'] = $nb;
}
if (($o['l'] <= $level) AND ($i > 0)) {
$prev = $lru[$o['l']];
$this->outlines[$prev]['next'] = $i;
$this->outlines[$i]['prev'] = $prev;
}
$lru[$o['l']] = $i;
$level = $o['l'];
}
$n = $this->n + 1;
$nltags = '/<br[\s]?\/>|<\/(blockquote|dd|dl|div|dt|h1|h2|h3|h4|h5|h6|hr|li|ol|p|pre|ul|tcpdf|table|tr|td)>/si';
foreach ($this->outlines as $i => $o) {
$oid = $this->_newobj();
$title = preg_replace($nltags, "\n", $o['t']);
$title = preg_replace("/[\r]+/si", '', $title);
$title = preg_replace("/[\n]+/si", "\n", $title);
$title = strip_tags($title);
$title = $this->stringTrim($title);
$out = '<</Title '.$this->_textstring($title, $oid);
$out .= ' /Parent '.($n + $o['parent']).' 0 R';
if (isset($o['prev'])) {
$out .= ' /Prev '.($n + $o['prev']).' 0 R';
}
if (isset($o['next'])) {
$out .= ' /Next '.($n + $o['next']).' 0 R';
}
if (isset($o['first'])) {
$out .= ' /First '.($n + $o['first']).' 0 R';
}
if (isset($o['last'])) {
$out .= ' /Last '.($n + $o['last']).' 0 R';
}
if (isset($o['u']) AND !empty($o['u'])) {
if (is_string($o['u'])) {
if ($o['u'][0] == '#') {
$out .= ' /Dest /'.TCPDF_STATIC::encodeNameObject(substr($o['u'], 1));
} elseif ($o['u'][0] == '%') {
$filename = basename(substr($o['u'], 1));
$out .= ' /A <</S /GoToE /D [0 /Fit] /NewWindow true /T << /R /C /P '.($o['p'] - 1).' /A '.$this->embeddedfiles[$filename]['a'].' >> >>';
} elseif ($o['u'][0] == '*') {
$filename = basename(substr($o['u'], 1));
$jsa = 'var D=event.target.doc;var MyData=D.dataObjects;for (var i in MyData) if (MyData[i].path=="'.$filename.'") D.exportDataObject( { cName : MyData[i].name, nLaunch : 2});';
$out .= ' /A <</S /JavaScript /JS '.$this->_textstring($jsa, $oid).'>>';
} else {
$out .= ' /A <</S /URI /URI '.$this->_datastring($this->unhtmlentities($o['u']), $oid).'>>';
}
} elseif (isset($this->links[$o['u']])) {
$l = $this->links[$o['u']];
if (isset($this->page_obj_id[($l['p'])])) {
$out .= sprintf(' /Dest [%u 0 R /XYZ 0 %F null]', $this->page_obj_id[($l['p'])], ($this->pagedim[$l['p']]['h'] - ($l['y'] * $this->k)));
}
}
} elseif (isset($this->page_obj_id[($o['p'])])) {
$out .= ' '.sprintf('/Dest [%u 0 R /XYZ %F %F null]', $this->page_obj_id[($o['p'])], ($o['x'] * $this->k), ($this->pagedim[$o['p']]['h'] - ($o['y'] * $this->k)));
}
$style = 0;
if (!empty($o['s'])) {
if (strpos($o['s'], 'B') !== false) {
$style |= 2;
}
if (strpos($o['s'], 'I') !== false) {
$style |= 1;
}
}
$out .= sprintf(' /F %d', $style);
if (isset($o['c']) AND is_array($o['c']) AND (count($o['c']) == 3)) {
$color = array_values($o['c']);
$out .= sprintf(' /C [%F %F %F]', ($color[0] / 255), ($color[1] / 255), ($color[2] / 255));
} else {
$out .= ' /C [0.0 0.0 0.0]';
}
$out .= ' /Count 0';
$out .= ' >>';
$out .= "\n".'endobj';
$this->_out($out);
}
$this->OutlineRoot = $this->_newobj();
$this->_out('<< /Type /Outlines /First '.$n.' 0 R /Last '.($n + $lru[0]).' 0 R >>'."\n".'endobj');
}
public function IncludeJS($script) {
$this->javascript .= $script;
}
public function addJavascriptObject($script, $onload=false) {
if ($this->pdfa_mode) {
return false;
}
++$this->n;
$this->js_objects[$this->n] = array('n' => $this->n, 'js' => $script, 'onload' => $onload);
return $this->n;
}
protected function _putjavascript() {
if ($this->pdfa_mode OR (empty($this->javascript) AND empty($this->js_objects))) {
return;
}
if (strpos($this->javascript, 'this.addField') > 0) {
if (!$this->ur['enabled']) {
}
$jsa = sprintf("ftcpdfdocsaved=this.addField('%s','%s',%d,[%F,%F,%F,%F]);", 'tcpdfdocsaved', 'text', 0, 0, 1, 0, 1);
$jsb = "getField('tcpdfdocsaved').value='saved';";
$this->javascript = $jsa."\n".$this->javascript."\n".$jsb;
}
$this->n_js = '<< /Names [';
if (!empty($this->javascript)) {
$this->n_js .= ' (EmbeddedJS) '.($this->n + 1).' 0 R';
}
if (!empty($this->js_objects)) {
foreach ($this->js_objects as $key => $val) {
if ($val['onload']) {
$this->n_js .= ' (JS'.$key.') '.$key.' 0 R';
}
}
}
$this->n_js .= ' ] >>';
if (!empty($this->javascript)) {
$obj_id = $this->_newobj();
$out = '<< /S /JavaScript';
$out .= ' /JS '.$this->_textstring($this->javascript, $obj_id);
$out .= ' >>';
$out .= "\n".'endobj';
$this->_out($out);
}
if (!empty($this->js_objects)) {
foreach ($this->js_objects as $key => $val) {
$out = $this->_getobj($key)."\n".' << /S /JavaScript /JS '.$this->_textstring($val['js'], $key).' >>'."\n".'endobj';
$this->_out($out);
}
}
}
protected function _addfield($type, $name, $x, $y, $w, $h, $prop) {
if ($this->rtl) {
$x = $x - $w;
}
$this->javascript .= "if (getField('tcpdfdocsaved').value != 'saved') {";
$k = $this->k;
$this->javascript .= sprintf("f".$name."=this.addField('%s','%s',%u,[%F,%F,%F,%F]);", $name, $type, $this->PageNo()-1, $x*$k, ($this->h-$y)*$k+1, ($x+$w)*$k, ($this->h-$y-$h)*$k+1)."\n";
$this->javascript .= 'f'.$name.'.textSize='.$this->FontSizePt.";\n";
foreach($prop as $key => $val) {
if (strcmp(substr($key, -5), 'Color') == 0) {
$val = TCPDF_COLORS::_JScolor($val);
} else {
$val = "'".$val."'";
}
$this->javascript .= 'f'.$name.'.'.$key.'='.$val.";\n";
}
if ($this->rtl) {
$this->x -= $w;
} else {
$this->x += $w;
}
$this->javascript .= '}';
}
public function setFormDefaultProp($prop=array()) {
$this->default_form_prop = $prop;
}
public function getFormDefaultProp() {
return $this->default_form_prop;
}
public function TextField($name, $w, $h, $prop=array(), $opt=array(), $x='', $y='', $js=false) {
if ($x === '') {
$x = $this->x;
}
if ($y === '') {
$y = $this->y;
}
list($x, $y) = $this->checkPageRegions($h, $x, $y);
if ($js) {
$this->_addfield('text', $name, $x, $y, $w, $h, $prop);
return;
}
$prop = array_merge($this->getFormDefaultProp(), $prop);
$popt = TCPDF_STATIC::getAnnotOptFromJSProp($prop, $this->spot_colors, $this->rtl);
$this->annotation_fonts[$this->CurrentFont['fontkey']] = $this->CurrentFont['i'];
$fontstyle = sprintf('/F%d %F Tf %s', $this->CurrentFont['i'], $this->FontSizePt, $this->TextColor);
$popt['da'] = $fontstyle;
$popt['ap'] = array();
$popt['ap']['n'] = '/Tx BMC q '.$fontstyle.' ';
$text = '';
if (isset($prop['value']) AND !empty($prop['value'])) {
$text = $prop['value'];
} elseif (isset($opt['v']) AND !empty($opt['v'])) {
$text = $opt['v'];
}
$tmpid = $this->startTemplate($w, $h, false);
$align = '';
if (isset($popt['q'])) {
switch ($popt['q']) {
case 0: {
$align = 'L';
break;
}
case 1: {
$align = 'C';
break;
}
case 2: {
$align = 'R';
break;
}
default: {
$align = '';
break;
}
}
}
$this->MultiCell($w, $h, $text, 0, $align, false, 0, 0, 0, true, 0, false, true, 0, 'T', false);
$this->endTemplate();
--$this->n;
$popt['ap']['n'] .= $this->xobjects[$tmpid]['outdata'];
unset($this->xobjects[$tmpid]);
$popt['ap']['n'] .= 'Q EMC';
$opt = array_merge($popt, $opt);
unset($opt['bs']);
$opt['Subtype'] = 'Widget';
$opt['ft'] = 'Tx';
$opt['t'] = $name;
unset($opt['mk']['ca']);
unset($opt['mk']['rc']);
unset($opt['mk']['ac']);
unset($opt['mk']['i']);
unset($opt['mk']['ri']);
unset($opt['mk']['ix']);
unset($opt['mk']['if']);
unset($opt['mk']['tp']);
$this->Annotation($x, $y, $w, $h, $name, $opt, 0);
if ($this->rtl) {
$this->x -= $w;
} else {
$this->x += $w;
}
}
public function RadioButton($name, $w, $prop=array(), $opt=array(), $onvalue='On', $checked=false, $x='', $y='', $js=false) {
if ($x === '') {
$x = $this->x;
}
if ($y === '') {
$y = $this->y;
}
list($x, $y) = $this->checkPageRegions($w, $x, $y);
if ($js) {
$this->_addfield('radiobutton', $name, $x, $y, $w, $w, $prop);
return;
}
if (TCPDF_STATIC::empty_string($onvalue)) {
$onvalue = 'On';
}
if ($checked) {
$defval = $onvalue;
} else {
$defval = 'Off';
}
$font = 'zapfdingbats';
if ($this->pdfa_mode) {
$font = 'pdfa'.$font;
}
$this->AddFont($font);
$tmpfont = $this->getFontBuffer($font);
if (!isset($this->radiobutton_groups[$this->page])) {
$this->radiobutton_groups[$this->page] = array();
}
if (!isset($this->radiobutton_groups[$this->page][$name])) {
$this->radiobutton_groups[$this->page][$name] = array();
++$this->n;
$this->radiobutton_groups[$this->page][$name]['n'] = $this->n;
$this->radio_groups[] = $this->n;
}
$kid = ($this->n + 1);
$this->radiobutton_groups[$this->page][$name][] = array('kid' => $kid, 'def' => $defval);
$prop = array_merge($this->getFormDefaultProp(), $prop);
$prop['NoToggleToOff'] = 'true';
$prop['Radio'] = 'true';
$prop['borderStyle'] = 'inset';
$popt = TCPDF_STATIC::getAnnotOptFromJSProp($prop, $this->spot_colors, $this->rtl);
$this->annotation_fonts[$tmpfont['fontkey']] = $tmpfont['i'];
$fontstyle = sprintf('/F%d %F Tf %s', $tmpfont['i'], $this->FontSizePt, $this->TextColor);
$popt['da'] = $fontstyle;
$popt['ap'] = array();
$popt['ap']['n'] = array();
$fx = ((($w - $this->getAbsFontMeasure($tmpfont['cw'][108])) / 2) * $this->k);
$fy = (($w - ((($tmpfont['desc']['Ascent'] - $tmpfont['desc']['Descent']) * $this->FontSizePt / 1000) / $this->k)) * $this->k);
$popt['ap']['n'][$onvalue] = sprintf('q %s BT /F%d %F Tf %F %F Td ('.chr(108).') Tj ET Q', $this->TextColor, $tmpfont['i'], $this->FontSizePt, $fx, $fy);
$popt['ap']['n']['Off'] = sprintf('q %s BT /F%d %F Tf %F %F Td ('.chr(109).') Tj ET Q', $this->TextColor, $tmpfont['i'], $this->FontSizePt, $fx, $fy);
if (!isset($popt['mk'])) {
$popt['mk'] = array();
}
$popt['mk']['ca'] = '(l)';
$opt = array_merge($popt, $opt);
$opt['Subtype'] = 'Widget';
$opt['ft'] = 'Btn';
if ($checked) {
$opt['v'] = array('/'.$onvalue);
$opt['as'] = $onvalue;
} else {
$opt['as'] = 'Off';
}
if (!isset($this->radiobutton_groups[$this->page][$name]['#readonly#'])) {
$this->radiobutton_groups[$this->page][$name]['#readonly#'] = false;
}
$this->radiobutton_groups[$this->page][$name]['#readonly#'] |= ($opt['f'] & 64);
$this->Annotation($x, $y, $w, $w, $name, $opt, 0);
if ($this->rtl) {
$this->x -= $w;
} else {
$this->x += $w;
}
}
public function ListBox($name, $w, $h, $values, $prop=array(), $opt=array(), $x='', $y='', $js=false) {
if ($x === '') {
$x = $this->x;
}
if ($y === '') {
$y = $this->y;
}
list($x, $y) = $this->checkPageRegions($h, $x, $y);
if ($js) {
$this->_addfield('listbox', $name, $x, $y, $w, $h, $prop);
$s = '';
foreach ($values as $value) {
if (is_array($value)) {
$s .= ',[\''.addslashes($value[1]).'\',\''.addslashes($value[0]).'\']';
} else {
$s .= ',[\''.addslashes($value).'\',\''.addslashes($value).'\']';
}
}
$this->javascript .= 'f'.$name.'.setItems('.substr($s, 1).');'."\n";
return;
}
$prop = array_merge($this->getFormDefaultProp(), $prop);
$popt = TCPDF_STATIC::getAnnotOptFromJSProp($prop, $this->spot_colors, $this->rtl);
$this->annotation_fonts[$this->CurrentFont['fontkey']] = $this->CurrentFont['i'];
$fontstyle = sprintf('/F%d %F Tf %s', $this->CurrentFont['i'], $this->FontSizePt, $this->TextColor);
$popt['da'] = $fontstyle;
$popt['ap'] = array();
$popt['ap']['n'] = '/Tx BMC q '.$fontstyle.' ';
$text = '';
foreach($values as $item) {
if (is_array($item)) {
$text .= $item[1]."\n";
} else {
$text .= $item."\n";
}
}
$tmpid = $this->startTemplate($w, $h, false);
$this->MultiCell($w, $h, $text, 0, '', false, 0, 0, 0, true, 0, false, true, 0, 'T', false);
$this->endTemplate();
--$this->n;
$popt['ap']['n'] .= $this->xobjects[$tmpid]['outdata'];
unset($this->xobjects[$tmpid]);
$popt['ap']['n'] .= 'Q EMC';
$opt = array_merge($popt, $opt);
$opt['Subtype'] = 'Widget';
$opt['ft'] = 'Ch';
$opt['t'] = $name;
$opt['opt'] = $values;
unset($opt['mk']['ca']);
unset($opt['mk']['rc']);
unset($opt['mk']['ac']);
unset($opt['mk']['i']);
unset($opt['mk']['ri']);
unset($opt['mk']['ix']);
unset($opt['mk']['if']);
unset($opt['mk']['tp']);
$this->Annotation($x, $y, $w, $h, $name, $opt, 0);
if ($this->rtl) {
$this->x -= $w;
} else {
$this->x += $w;
}
}
public function ComboBox($name, $w, $h, $values, $prop=array(), $opt=array(), $x='', $y='', $js=false) {
if ($x === '') {
$x = $this->x;
}
if ($y === '') {
$y = $this->y;
}
list($x, $y) = $this->checkPageRegions($h, $x, $y);
if ($js) {
$this->_addfield('combobox', $name, $x, $y, $w, $h, $prop);
$s = '';
foreach ($values as $value) {
if (is_array($value)) {
$s .= ',[\''.addslashes($value[1]).'\',\''.addslashes($value[0]).'\']';
} else {
$s .= ',[\''.addslashes($value).'\',\''.addslashes($value).'\']';
}
}
$this->javascript .= 'f'.$name.'.setItems('.substr($s, 1).');'."\n";
return;
}
$prop = array_merge($this->getFormDefaultProp(), $prop);
$prop['Combo'] = true;
$popt = TCPDF_STATIC::getAnnotOptFromJSProp($prop, $this->spot_colors, $this->rtl);
$this->annotation_fonts[$this->CurrentFont['fontkey']] = $this->CurrentFont['i'];
$fontstyle = sprintf('/F%d %F Tf %s', $this->CurrentFont['i'], $this->FontSizePt, $this->TextColor);
$popt['da'] = $fontstyle;
$popt['ap'] = array();
$popt['ap']['n'] = '/Tx BMC q '.$fontstyle.' ';
$text = '';
foreach($values as $item) {
if (is_array($item)) {
$text .= $item[1]."\n";
} else {
$text .= $item."\n";
}
}
$tmpid = $this->startTemplate($w, $h, false);
$this->MultiCell($w, $h, $text, 0, '', false, 0, 0, 0, true, 0, false, true, 0, 'T', false);
$this->endTemplate();
--$this->n;
$popt['ap']['n'] .= $this->xobjects[$tmpid]['outdata'];
unset($this->xobjects[$tmpid]);
$popt['ap']['n'] .= 'Q EMC';
$opt = array_merge($popt, $opt);
$opt['Subtype'] = 'Widget';
$opt['ft'] = 'Ch';
$opt['t'] = $name;
$opt['opt'] = $values;
unset($opt['mk']['ca']);
unset($opt['mk']['rc']);
unset($opt['mk']['ac']);
unset($opt['mk']['i']);
unset($opt['mk']['ri']);
unset($opt['mk']['ix']);
unset($opt['mk']['if']);
unset($opt['mk']['tp']);
$this->Annotation($x, $y, $w, $h, $name, $opt, 0);
if ($this->rtl) {
$this->x -= $w;
} else {
$this->x += $w;
}
}
public function CheckBox($name, $w, $checked=false, $prop=array(), $opt=array(), $onvalue='Yes', $x='', $y='', $js=false) {
if ($x === '') {
$x = $this->x;
}
if ($y === '') {
$y = $this->y;
}
list($x, $y) = $this->checkPageRegions($w, $x, $y);
if ($js) {
$this->_addfield('checkbox', $name, $x, $y, $w, $w, $prop);
return;
}
if (!isset($prop['value'])) {
$prop['value'] = array('Yes');
}
$prop = array_merge($this->getFormDefaultProp(), $prop);
$prop['borderStyle'] = 'inset';
$popt = TCPDF_STATIC::getAnnotOptFromJSProp($prop, $this->spot_colors, $this->rtl);
$font = 'zapfdingbats';
if ($this->pdfa_mode) {
$font = 'pdfa'.$font;
}
$this->AddFont($font);
$tmpfont = $this->getFontBuffer($font);
$this->annotation_fonts[$tmpfont['fontkey']] = $tmpfont['i'];
$fontstyle = sprintf('/F%d %F Tf %s', $tmpfont['i'], $this->FontSizePt, $this->TextColor);
$popt['da'] = $fontstyle;
$popt['ap'] = array();
$popt['ap']['n'] = array();
$fx = ((($w - $this->getAbsFontMeasure($tmpfont['cw'][110])) / 2) * $this->k);
$fy = (($w - ((($tmpfont['desc']['Ascent'] - $tmpfont['desc']['Descent']) * $this->FontSizePt / 1000) / $this->k)) * $this->k);
$popt['ap']['n']['Yes'] = sprintf('q %s BT /F%d %F Tf %F %F Td ('.chr(110).') Tj ET Q', $this->TextColor, $tmpfont['i'], $this->FontSizePt, $fx, $fy);
$popt['ap']['n']['Off'] = sprintf('q %s BT /F%d %F Tf %F %F Td ('.chr(111).') Tj ET Q', $this->TextColor, $tmpfont['i'], $this->FontSizePt, $fx, $fy);
$opt = array_merge($popt, $opt);
$opt['Subtype'] = 'Widget';
$opt['ft'] = 'Btn';
$opt['t'] = $name;
if (TCPDF_STATIC::empty_string($onvalue)) {
$onvalue = 'Yes';
}
$opt['opt'] = array($onvalue);
if ($checked) {
$opt['v'] = array('/Yes');
$opt['as'] = 'Yes';
} else {
$opt['v'] = array('/Off');
$opt['as'] = 'Off';
}
$this->Annotation($x, $y, $w, $w, $name, $opt, 0);
if ($this->rtl) {
$this->x -= $w;
} else {
$this->x += $w;
}
}
public function Button($name, $w, $h, $caption, $action, $prop=array(), $opt=array(), $x='', $y='', $js=false) {
if ($x === '') {
$x = $this->x;
}
if ($y === '') {
$y = $this->y;
}
list($x, $y) = $this->checkPageRegions($h, $x, $y);
if ($js) {
$this->_addfield('button', $name, $this->x, $this->y, $w, $h, $prop);
$this->javascript .= 'f'.$name.".buttonSetCaption('".addslashes($caption)."');\n";
$this->javascript .= 'f'.$name.".setAction('MouseUp','".addslashes($action)."');\n";
$this->javascript .= 'f'.$name.".highlight='push';\n";
$this->javascript .= 'f'.$name.".print=false;\n";
return;
}
$prop = array_merge($this->getFormDefaultProp(), $prop);
$prop['Pushbutton'] = 'true';
$prop['highlight'] = 'push';
$prop['display'] = 'display.noPrint';
$popt = TCPDF_STATIC::getAnnotOptFromJSProp($prop, $this->spot_colors, $this->rtl);
$this->annotation_fonts[$this->CurrentFont['fontkey']] = $this->CurrentFont['i'];
$fontstyle = sprintf('/F%d %F Tf %s', $this->CurrentFont['i'], $this->FontSizePt, $this->TextColor);
$popt['da'] = $fontstyle;
$popt['ap'] = array();
$popt['ap']['n'] = '/Tx BMC q '.$fontstyle.' ';
$tmpid = $this->startTemplate($w, $h, false);
$bw = (2 / $this->k);
$border = array(
'L' => array('width' => $bw, 'cap' => 'square', 'join' => 'miter', 'dash' => 0, 'color' => array(231)),
'R' => array('width' => $bw, 'cap' => 'square', 'join' => 'miter', 'dash' => 0, 'color' => array(51)),
'T' => array('width' => $bw, 'cap' => 'square', 'join' => 'miter', 'dash' => 0, 'color' => array(231)),
'B' => array('width' => $bw, 'cap' => 'square', 'join' => 'miter', 'dash' => 0, 'color' => array(51)));
$this->SetFillColor(204);
$this->Cell($w, $h, $caption, $border, 0, 'C', true, '', 1, false, 'T', 'M');
$this->endTemplate();
--$this->n;
$popt['ap']['n'] .= $this->xobjects[$tmpid]['outdata'];
unset($this->xobjects[$tmpid]);
$popt['ap']['n'] .= 'Q EMC';
if (!isset($popt['mk'])) {
$popt['mk'] = array();
}
$ann_obj_id = ($this->n + 1);
if (!empty($action) AND !is_array($action)) {
$ann_obj_id = ($this->n + 2);
}
$popt['mk']['ca'] = $this->_textstring($caption, $ann_obj_id);
$popt['mk']['rc'] = $this->_textstring($caption, $ann_obj_id);
$popt['mk']['ac'] = $this->_textstring($caption, $ann_obj_id);
$opt = array_merge($popt, $opt);
$opt['Subtype'] = 'Widget';
$opt['ft'] = 'Btn';
$opt['t'] = $caption;
$opt['v'] = $name;
if (!empty($action)) {
if (is_array($action)) {
$opt['aa'] = '/D <<';
$bmode = array('SubmitForm', 'ResetForm', 'ImportData');
foreach ($action AS $key => $val) {
if (($key == 'S') AND in_array($val, $bmode)) {
$opt['aa'] .= ' /S /'.$val;
} elseif (($key == 'F') AND (!empty($val))) {
$opt['aa'] .= ' /F '.$this->_datastring($val, $ann_obj_id);
} elseif (($key == 'Fields') AND is_array($val) AND !empty($val)) {
$opt['aa'] .= ' /Fields [';
foreach ($val AS $field) {
$opt['aa'] .= ' '.$this->_textstring($field, $ann_obj_id);
}
$opt['aa'] .= ']';
} elseif (($key == 'Flags')) {
$ff = 0;
if (is_array($val)) {
foreach ($val AS $flag) {
switch ($flag) {
case 'Include/Exclude': {
$ff += 1 << 0;
break;
}
case 'IncludeNoValueFields': {
$ff += 1 << 1;
break;
}
case 'ExportFormat': {
$ff += 1 << 2;
break;
}
case 'GetMethod': {
$ff += 1 << 3;
break;
}
case 'SubmitCoordinates': {
$ff += 1 << 4;
break;
}
case 'XFDF': {
$ff += 1 << 5;
break;
}
case 'IncludeAppendSaves': {
$ff += 1 << 6;
break;
}
case 'IncludeAnnotations': {
$ff += 1 << 7;
break;
}
case 'SubmitPDF': {
$ff += 1 << 8;
break;
}
case 'CanonicalFormat': {
$ff += 1 << 9;
break;
}
case 'ExclNonUserAnnots': {
$ff += 1 << 10;
break;
}
case 'ExclFKey': {
$ff += 1 << 11;
break;
}
case 'EmbedForm': {
$ff += 1 << 13;
break;
}
}
}
} else {
$ff = intval($val);
}
$opt['aa'] .= ' /Flags '.$ff;
}
}
$opt['aa'] .= ' >>';
} else {
$js_obj_id = $this->addJavascriptObject($action);
$opt['aa'] = '/D '.$js_obj_id.' 0 R';
}
}
$this->Annotation($x, $y, $w, $h, $name, $opt, 0);
if ($this->rtl) {
$this->x -= $w;
} else {
$this->x += $w;
}
}
protected function _putsignature() {
if ((!$this->sign) OR (!isset($this->signature_data['cert_type']))) {
return;
}
$sigobjid = ($this->sig_obj_id + 1);
$out = $this->_getobj($sigobjid)."\n";
$out .= '<< /Type /Sig';
$out .= ' /Filter /Adobe.PPKLite';
$out .= ' /SubFilter /adbe.pkcs7.detached';
$out .= ' '.TCPDF_STATIC::$byterange_string;
$out .= ' /Contents<'.str_repeat('0', $this->signature_max_length).'>';
if (empty($this->signature_data['approval']) OR ($this->signature_data['approval'] != 'A')) {
$out .= ' /Reference [';
$out .= ' << /Type /SigRef';
if ($this->signature_data['cert_type'] > 0) {
$out .= ' /TransformMethod /DocMDP';
$out .= ' /TransformParams <<';
$out .= ' /Type /TransformParams';
$out .= ' /P '.$this->signature_data['cert_type'];
$out .= ' /V /1.2';
} else {
$out .= ' /TransformMethod /UR3';
$out .= ' /TransformParams <<';
$out .= ' /Type /TransformParams';
$out .= ' /V /2.2';
if (!TCPDF_STATIC::empty_string($this->ur['document'])) {
$out .= ' /Document['.$this->ur['document'].']';
}
if (!TCPDF_STATIC::empty_string($this->ur['form'])) {
$out .= ' /Form['.$this->ur['form'].']';
}
if (!TCPDF_STATIC::empty_string($this->ur['signature'])) {
$out .= ' /Signature['.$this->ur['signature'].']';
}
if (!TCPDF_STATIC::empty_string($this->ur['annots'])) {
$out .= ' /Annots['.$this->ur['annots'].']';
}
if (!TCPDF_STATIC::empty_string($this->ur['ef'])) {
$out .= ' /EF['.$this->ur['ef'].']';
}
if (!TCPDF_STATIC::empty_string($this->ur['formex'])) {
$out .= ' /FormEX['.$this->ur['formex'].']';
}
}
$out .= ' >>';
$out .= ' >>';
$out .= ' ]';
}
if (isset($this->signature_data['info']['Name']) AND !TCPDF_STATIC::empty_string($this->signature_data['info']['Name'])) {
$out .= ' /Name '.$this->_textstring($this->signature_data['info']['Name'], $sigobjid);
}
if (isset($this->signature_data['info']['Location']) AND !TCPDF_STATIC::empty_string($this->signature_data['info']['Location'])) {
$out .= ' /Location '.$this->_textstring($this->signature_data['info']['Location'], $sigobjid);
}
if (isset($this->signature_data['info']['Reason']) AND !TCPDF_STATIC::empty_string($this->signature_data['info']['Reason'])) {
$out .= ' /Reason '.$this->_textstring($this->signature_data['info']['Reason'], $sigobjid);
}
if (isset($this->signature_data['info']['ContactInfo']) AND !TCPDF_STATIC::empty_string($this->signature_data['info']['ContactInfo'])) {
$out .= ' /ContactInfo '.$this->_textstring($this->signature_data['info']['ContactInfo'], $sigobjid);
}
$out .= ' /M '.$this->_datestring($sigobjid, $this->doc_modification_timestamp);
$out .= ' >>';
$out .= "\n".'endobj';
$this->_out($out);
}
public function setUserRights(
$enable=true,
$document='/FullSave',
$annots='/Create/Delete/Modify/Copy/Import/Export',
$form='/Add/Delete/FillIn/Import/Export/SubmitStandalone/SpawnTemplate',
$signature='/Modify',
$ef='/Create/Delete/Modify/Import',
$formex='') {
$this->ur['enabled'] = $enable;
$this->ur['document'] = $document;
$this->ur['annots'] = $annots;
$this->ur['form'] = $form;
$this->ur['signature'] = $signature;
$this->ur['ef'] = $ef;
$this->ur['formex'] = $formex;
if (!$this->sign) {
$this->setSignature('', '', '', '', 0, array());
}
}
public function setSignature($signing_cert='', $private_key='', $private_key_password='', $extracerts='', $cert_type=2, $info=array(), $approval='') {
$this->sign = true;
++$this->n;
$this->sig_obj_id = $this->n;
++$this->n;
$this->signature_data = array();
if (strlen($signing_cert) == 0) {
$this->Error('Please provide a certificate file and password!');
}
if (strlen($private_key) == 0) {
$private_key = $signing_cert;
}
$this->signature_data['signcert'] = $signing_cert;
$this->signature_data['privkey'] = $private_key;
$this->signature_data['password'] = $private_key_password;
$this->signature_data['extracerts'] = $extracerts;
$this->signature_data['cert_type'] = $cert_type;
$this->signature_data['info'] = $info;
$this->signature_data['approval'] = $approval;
}
public function setSignatureAppearance($x=0, $y=0, $w=0, $h=0, $page=-1, $name='') {
$this->signature_appearance = $this->getSignatureAppearanceArray($x, $y, $w, $h, $page, $name);
}
public function addEmptySignatureAppearance($x=0, $y=0, $w=0, $h=0, $page=-1, $name='') {
++$this->n;
$this->empty_signature_appearance[] = array('objid' => $this->n) + $this->getSignatureAppearanceArray($x, $y, $w, $h, $page, $name);
}
protected function getSignatureAppearanceArray($x=0, $y=0, $w=0, $h=0, $page=-1, $name='') {
$sigapp = array();
if (($page < 1) OR ($page > $this->numpages)) {
$sigapp['page'] = $this->page;
} else {
$sigapp['page'] = intval($page);
}
if (empty($name)) {
$sigapp['name'] = 'Signature';
} else {
$sigapp['name'] = $name;
}
$a = $x * $this->k;
$b = $this->pagedim[($sigapp['page'])]['h'] - (($y + $h) * $this->k);
$c = $w * $this->k;
$d = $h * $this->k;
$sigapp['rect'] = sprintf('%F %F %F %F', $a, $b, ($a + $c), ($b + $d));
return $sigapp;
}
public function setTimeStamp($tsa_host='', $tsa_username='', $tsa_password='', $tsa_cert='') {
$this->tsa_data = array();
if (!function_exists('curl_init')) {
$this->Error('Please enable cURL PHP extension!');
}
if (strlen($tsa_host) == 0) {
$this->Error('Please specify the host of Time Stamping Authority (TSA)!');
}
$this->tsa_data['tsa_host'] = $tsa_host;
if (is_file($tsa_username)) {
$this->tsa_data['tsa_auth'] = $tsa_username;
} else {
$this->tsa_data['tsa_username'] = $tsa_username;
}
$this->tsa_data['tsa_password'] = $tsa_password;
$this->tsa_data['tsa_cert'] = $tsa_cert;
$this->tsa_timestamp = true;
}
protected function applyTSA($signature) {
if (!$this->tsa_timestamp) {
return $signature;
}
return $signature;
}
public function startPageGroup($page='') {
if (empty($page)) {
$page = $this->page + 1;
}
$this->newpagegroup[$page] = sizeof($this->newpagegroup) + 1;
}
public function setStartingPageNumber($num=1) {
$this->starting_page_number = max(0, intval($num));
}
public function getAliasRightShift() {
$ref = '{'.TCPDF_STATIC::$alias_right_shift.'}{'.TCPDF_STATIC::$alias_tot_pages.'}{'.TCPDF_STATIC::$alias_num_page.'}';
$rep = str_repeat(' ', $this->GetNumChars($ref));
$wrep = $this->GetStringWidth($rep);
if ($wrep > 0) {
$wdiff = max(1, ($this->GetStringWidth($ref) / $wrep));
} else {
$wdiff = 1;
}
$sdiff = sprintf('%F', $wdiff);
$alias = TCPDF_STATIC::$alias_right_shift.$sdiff.'}';
if ($this->isUnicodeFont()) {
$alias = '{'.$alias;
}
return $alias;
}
public function getAliasNbPages() {
if ($this->isUnicodeFont()) {
return '{'.TCPDF_STATIC::$alias_tot_pages.'}';
}
return TCPDF_STATIC::$alias_tot_pages;
}
public function getAliasNumPage() {
if ($this->isUnicodeFont()) {
return '{'.TCPDF_STATIC::$alias_num_page.'}';
}
return TCPDF_STATIC::$alias_num_page;
}
public function getPageGroupAlias() {
if ($this->isUnicodeFont()) {
return '{'.TCPDF_STATIC::$alias_group_tot_pages.'}';
}
return TCPDF_STATIC::$alias_group_tot_pages;
}
public function getPageNumGroupAlias() {
if ($this->isUnicodeFont()) {
return '{'.TCPDF_STATIC::$alias_group_num_page.'}';
}
return TCPDF_STATIC::$alias_group_num_page;
}
public function getGroupPageNo() {
return $this->pagegroups[$this->currpagegroup];
}
public function getGroupPageNoFormatted() {
return TCPDF_STATIC::formatPageNumber($this->getGroupPageNo());
}
public function PageNoFormatted() {
return TCPDF_STATIC::formatPageNumber($this->PageNo());
}
protected function _putocg() {
if (empty($this->pdflayers)) {
return;
}
foreach ($this->pdflayers as $key => $layer) {
$this->pdflayers[$key]['objid'] = $this->_newobj();
$out = '<< /Type /OCG';
$out .= ' /Name '.$this->_textstring($layer['name'], $this->pdflayers[$key]['objid']);
$out .= ' /Usage <<';
if (isset($layer['print']) AND ($layer['print'] !== NULL)) {
$out .= ' /Print <</PrintState /'.($layer['print']?'ON':'OFF').'>>';
}
$out .= ' /View <</ViewState /'.($layer['view']?'ON':'OFF').'>>';
$out .= ' >> >>';
$out .= "\n".'endobj';
$this->_out($out);
}
}
public function startLayer($name='', $print=true, $view=true, $lock=true) {
if ($this->state != 2) {
return;
}
$layer = sprintf('LYR%03d', (count($this->pdflayers) + 1));
if (empty($name)) {
$name = $layer;
} else {
$name = preg_replace('/[^a-zA-Z0-9_\-]/', '', $name);
}
$this->pdflayers[] = array('layer' => $layer, 'name' => $name, 'print' => $print, 'view' => $view, 'lock' => $lock);
$this->openMarkedContent = true;
$this->_out('/OC /'.$layer.' BDC');
}
public function endLayer() {
if ($this->state != 2) {
return;
}
if ($this->openMarkedContent) {
$this->_out('EMC');
$this->openMarkedContent = false;
}
}
public function setVisibility($v) {
if ($this->state != 2) {
return;
}
$this->endLayer();
switch($v) {
case 'print': {
$this->startLayer('Print', true, false);
break;
}
case 'view':
case 'screen': {
$this->startLayer('View', false, true);
break;
}
case 'all': {
$this->_out('');
break;
}
default: {
$this->Error('Incorrect visibility: '.$v);
break;
}
}
}
protected function addExtGState($parms) {
if ($this->pdfa_mode) {
return;
}
foreach ($this->extgstates as $i => $ext) {
if ($ext['parms'] == $parms) {
if ($this->inxobj) {
$this->xobjects[$this->xobjid]['extgstates'][$i] = $ext;
}
return $i;
}
}
$n = (count($this->extgstates) + 1);
$this->extgstates[$n] = array('parms' => $parms);
if ($this->inxobj) {
$this->xobjects[$this->xobjid]['extgstates'][$n] = $this->extgstates[$n];
}
return $n;
}
protected function setExtGState($gs) {
if ($this->pdfa_mode OR ($this->state != 2)) {
return;
}
$this->_out(sprintf('/GS%d gs', $gs));
}
protected function _putextgstates() {
foreach ($this->extgstates as $i => $ext) {
$this->extgstates[$i]['n'] = $this->_newobj();
$out = '<< /Type /ExtGState';
foreach ($ext['parms'] as $k => $v) {
if (is_float($v)) {
$v = sprintf('%F', $v);
} elseif ($v === true) {
$v = 'true';
} elseif ($v === false) {
$v = 'false';
}
$out .= ' /'.$k.' '.$v;
}
$out .= ' >>';
$out .= "\n".'endobj';
$this->_out($out);
}
}
public function setOverprint($stroking=true, $nonstroking='', $mode=0) {
if ($this->state != 2) {
return;
}
$stroking = $stroking ? true : false;
if (TCPDF_STATIC::empty_string($nonstroking)) {
$nonstroking = $stroking;
} else {
$nonstroking = $nonstroking ? true : false;
}
if (($mode != 0) AND ($mode != 1)) {
$mode = 0;
}
$this->overprint = array('OP' => $stroking, 'op' => $nonstroking, 'OPM' => $mode);
$gs = $this->addExtGState($this->overprint);
$this->setExtGState($gs);
}
public function getOverprint() {
return $this->overprint;
}
public function setAlpha($stroking=1, $bm='Normal', $nonstroking='', $ais=false) {
if ($this->pdfa_mode) {
return;
}
$stroking = floatval($stroking);
if (TCPDF_STATIC::empty_string($nonstroking)) {
$nonstroking = $stroking;
} else {
$nonstroking = floatval($nonstroking);
}
if ($bm[0] == '/') {
$bm = substr($bm, 1);
}
if (!in_array($bm, array('Normal', 'Multiply', 'Screen', 'Overlay', 'Darken', 'Lighten', 'ColorDodge', 'ColorBurn', 'HardLight', 'SoftLight', 'Difference', 'Exclusion', 'Hue', 'Saturation', 'Color', 'Luminosity'))) {
$bm = 'Normal';
}
$ais = $ais ? true : false;
$this->alpha = array('CA' => $stroking, 'ca' => $nonstroking, 'BM' => '/'.$bm, 'AIS' => $ais);
$gs = $this->addExtGState($this->alpha);
$this->setExtGState($gs);
}
public function getAlpha() {
return $this->alpha;
}
public function setJPEGQuality($quality) {
if (($quality < 1) OR ($quality > 100)) {
$quality = 75;
}
$this->jpeg_quality = intval($quality);
}
public function setDefaultTableColumns($cols=4) {
$this->default_table_columns = intval($cols);
}
public function setCellHeightRatio($h) {
$this->cell_height_ratio = $h;
}
public function getCellHeightRatio() {
return $this->cell_height_ratio;
}
public function setPDFVersion($version='1.7') {
if ($this->pdfa_mode) {
$this->PDFVersion = '1.4';
} else {
$this->PDFVersion = $version;
}
}
public function setViewerPreferences($preferences) {
$this->viewer_preferences = $preferences;
}
public function colorRegistrationBar($x, $y, $w, $h, $transition=true, $vertical=false, $colors='A,R,G,B,C,M,Y,K') {
if (strpos($colors, 'ALLSPOT') !== false) {
$spot_colors = '';
foreach ($this->spot_colors as $spot_color_name => $v) {
$spot_colors .= ','.$spot_color_name;
}
if (!empty($spot_colors)) {
$spot_colors = substr($spot_colors, 1);
$colors = str_replace('ALLSPOT', $spot_colors, $colors);
} else {
$colors = str_replace('ALLSPOT', 'NONE', $colors);
}
}
$bars = explode(',', $colors);
$numbars = count($bars);
if ($numbars <= 0) {
return;
}
if ($vertical) {
$coords = array(0, 0, 0, 1);
$wb = $w / $numbars;
$hb = $h;
$xd = $wb;
$yd = 0;
} else {
$coords = array(1, 0, 0, 0);
$wb = $w;
$hb = $h / $numbars;
$xd = 0;
$yd = $hb;
}
$xb = $x;
$yb = $y;
foreach ($bars as $col) {
switch ($col) {
case 'A': {
$col_a = array(255);
$col_b = array(0);
break;
}
case 'W': {
$col_a = array(0);
$col_b = array(255);
break;
}
case 'R': {
$col_a = array(255,255,255);
$col_b = array(255,0,0);
break;
}
case 'G': {
$col_a = array(255,255,255);
$col_b = array(0,255,0);
break;
}
case 'B': {
$col_a = array(255,255,255);
$col_b = array(0,0,255);
break;
}
case 'C': {
$col_a = array(0,0,0,0);
$col_b = array(100,0,0,0);
break;
}
case 'M': {
$col_a = array(0,0,0,0);
$col_b = array(0,100,0,0);
break;
}
case 'Y': {
$col_a = array(0,0,0,0);
$col_b = array(0,0,100,0);
break;
}
case 'K': {
$col_a = array(0,0,0,0);
$col_b = array(0,0,0,100);
break;
}
case 'RGB': {
$col_a = array(255,255,255);
$col_b = array(0,0,0);
break;
}
case 'CMYK': {
$col_a = array(0,0,0,0);
$col_b = array(100,100,100,100);
break;
}
case 'ALL': {
$col_a = array(0,0,0,0,'None');
$col_b = array(100,100,100,100,'All');
break;
}
case 'NONE': {
$col_a = array(0,0,0,0,'None');
$col_b = array(0,0,0,0,'None');
break;
}
default: {
$col_a = array(0,0,0,0,'None');
$col_b = TCPDF_COLORS::getSpotColor($col, $this->spot_colors);
if ($col_b === false) {
$col_b = array(100,100,100,100,'All');
}
break;
}
}
if ($col != 'NONE') {
if ($transition) {
$this->LinearGradient($xb, $yb, $wb, $hb, $col_a, $col_b, $coords);
} else {
$this->SetFillColorArray($col_b);
$this->Rect($xb, $yb, $wb, $hb, 'F', array());
}
$xb += $xd;
$yb += $yd;
}
}
}
public function cropMark($x, $y, $w, $h, $type='T,R,B,L', $color=array(100,100,100,100,'All')) {
$this->SetLineStyle(array('width' => (0.5 / $this->k), 'cap' => 'butt', 'join' => 'miter', 'dash' => 0, 'color' => $color));
$type = strtoupper($type);
$type = preg_replace('/[^A-Z\-\,]*/', '', $type);
$type = str_replace('-', ',', $type);
$type = str_replace('TL', 'T,L', $type);
$type = str_replace('TR', 'T,R', $type);
$type = str_replace('BL', 'F,L', $type);
$type = str_replace('BR', 'F,R', $type);
$type = str_replace('A', 'T,L', $type);
$type = str_replace('B', 'T,R', $type);
$type = str_replace('T,RO', 'BO', $type);
$type = str_replace('C', 'F,L', $type);
$type = str_replace('D', 'F,R', $type);
$crops = explode(',', strtoupper($type));
$crops = array_unique($crops);
$dw = ($w / 4);
$dh = ($h / 4);
foreach ($crops as $crop) {
switch ($crop) {
case 'T':
case 'TOP': {
$x1 = $x;
$y1 = ($y - $h);
$x2 = $x;
$y2 = ($y - $dh);
break;
}
case 'F':
case 'BOTTOM': {
$x1 = $x;
$y1 = ($y + $dh);
$x2 = $x;
$y2 = ($y + $h);
break;
}
case 'L':
case 'LEFT': {
$x1 = ($x - $w);
$y1 = $y;
$x2 = ($x - $dw);
$y2 = $y;
break;
}
case 'R':
case 'RIGHT': {
$x1 = ($x + $dw);
$y1 = $y;
$x2 = ($x + $w);
$y2 = $y;
break;
}
}
$this->Line($x1, $y1, $x2, $y2);
}
}
public function registrationMark($x, $y, $r, $double=false, $cola=array(100,100,100,100,'All'), $colb=array(0,0,0,0,'None')) {
$line_style = array('width' => max((0.5 / $this->k),($r / 30)), 'cap' => 'butt', 'join' => 'miter', 'dash' => 0, 'color' => $cola);
$this->SetFillColorArray($cola);
$this->PieSector($x, $y, $r, 90, 180, 'F');
$this->PieSector($x, $y, $r, 270, 360, 'F');
$this->Circle($x, $y, $r, 0, 360, 'C', $line_style, array(), 8);
if ($double) {
$ri = $r * 0.5;
$this->SetFillColorArray($colb);
$this->PieSector($x, $y, $ri, 90, 180, 'F');
$this->PieSector($x, $y, $ri, 270, 360, 'F');
$this->SetFillColorArray($cola);
$this->PieSector($x, $y, $ri, 0, 90, 'F');
$this->PieSector($x, $y, $ri, 180, 270, 'F');
$this->Circle($x, $y, $ri, 0, 360, 'C', $line_style, array(), 8);
}
}
public function registrationMarkCMYK($x, $y, $r) {
$lw = max((0.5 / $this->k),($r / 8));
$ri = ($r * 0.6);
$re = ($r * 1.3);
$this->SetFillColorArray(array(100,0,0,0));
$this->PieSector($x, $y, $ri, 270, 360, 'F');
$this->SetFillColorArray(array(0,100,0,0));
$this->PieSector($x, $y, $ri, 0, 90, 'F');
$this->SetFillColorArray(array(0,0,100,0));
$this->PieSector($x, $y, $ri, 90, 180, 'F');
$this->SetFillColorArray(array(0,0,0,100));
$this->PieSector($x, $y, $ri, 180, 270, 'F');
$line_style = array('width' => $lw, 'cap' => 'butt', 'join' => 'miter', 'dash' => 0, 'color' => array(100,100,100,100,'All'));
$this->SetFillColorArray(array(100,100,100,100,'All'));
$this->Circle($x, $y, $r, 0, 360, 'C', $line_style, array(), 8);
$this->Line($x, ($y - $re), $x, ($y - $ri));
$this->Line($x, ($y + $ri), $x, ($y + $re));
$this->Line(($x - $re), $y, ($x - $ri), $y);
$this->Line(($x + $ri), $y, ($x + $re), $y);
}
public function LinearGradient($x, $y, $w, $h, $col1=array(), $col2=array(), $coords=array(0,0,1,0)) {
$this->Clip($x, $y, $w, $h);
$this->Gradient(2, $coords, array(array('color' => $col1, 'offset' => 0, 'exponent' => 1), array('color' => $col2, 'offset' => 1, 'exponent' => 1)), array(), false);
}
public function RadialGradient($x, $y, $w, $h, $col1=array(), $col2=array(), $coords=array(0.5,0.5,0.5,0.5,1)) {
$this->Clip($x, $y, $w, $h);
$this->Gradient(3, $coords, array(array('color' => $col1, 'offset' => 0, 'exponent' => 1), array('color' => $col2, 'offset' => 1, 'exponent' => 1)), array(), false);
}
public function CoonsPatchMesh($x, $y, $w, $h, $col1=array(), $col2=array(), $col3=array(), $col4=array(), $coords=array(0.00,0.0,0.33,0.00,0.67,0.00,1.00,0.00,1.00,0.33,1.00,0.67,1.00,1.00,0.67,1.00,0.33,1.00,0.00,1.00,0.00,0.67,0.00,0.33), $coords_min=0, $coords_max=1, $antialias=false) {
if ($this->pdfa_mode OR ($this->state != 2)) {
return;
}
$this->Clip($x, $y, $w, $h);
$n = count($this->gradients) + 1;
$this->gradients[$n] = array();
$this->gradients[$n]['type'] = 6;
$this->gradients[$n]['coords'] = array();
$this->gradients[$n]['antialias'] = $antialias;
$this->gradients[$n]['colors'] = array();
$this->gradients[$n]['transparency'] = false;
if (!isset($coords[0]['f'])) {
if (!isset($col1[1])) {
$col1[1] = $col1[2] = $col1[0];
}
if (!isset($col2[1])) {
$col2[1] = $col2[2] = $col2[0];
}
if (!isset($col3[1])) {
$col3[1] = $col3[2] = $col3[0];
}
if (!isset($col4[1])) {
$col4[1] = $col4[2] = $col4[0];
}
$patch_array[0]['f'] = 0;
$patch_array[0]['points'] = $coords;
$patch_array[0]['colors'][0]['r'] = $col1[0];
$patch_array[0]['colors'][0]['g'] = $col1[1];
$patch_array[0]['colors'][0]['b'] = $col1[2];
$patch_array[0]['colors'][1]['r'] = $col2[0];
$patch_array[0]['colors'][1]['g'] = $col2[1];
$patch_array[0]['colors'][1]['b'] = $col2[2];
$patch_array[0]['colors'][2]['r'] = $col3[0];
$patch_array[0]['colors'][2]['g'] = $col3[1];
$patch_array[0]['colors'][2]['b'] = $col3[2];
$patch_array[0]['colors'][3]['r'] = $col4[0];
$patch_array[0]['colors'][3]['g'] = $col4[1];
$patch_array[0]['colors'][3]['b'] = $col4[2];
} else {
$patch_array = $coords;
}
$bpcd = 65535;
$this->gradients[$n]['stream'] = '';
$count_patch = count($patch_array);
for ($i=0; $i < $count_patch; ++$i) {
$this->gradients[$n]['stream'] .= chr($patch_array[$i]['f']);
$count_points = count($patch_array[$i]['points']);
for ($j=0; $j < $count_points; ++$j) {
$patch_array[$i]['points'][$j] = (($patch_array[$i]['points'][$j] - $coords_min) / ($coords_max - $coords_min)) * $bpcd;
if ($patch_array[$i]['points'][$j] < 0) {
$patch_array[$i]['points'][$j] = 0;
}
if ($patch_array[$i]['points'][$j] > $bpcd) {
$patch_array[$i]['points'][$j] = $bpcd;
}
$this->gradients[$n]['stream'] .= chr(floor($patch_array[$i]['points'][$j] / 256));
$this->gradients[$n]['stream'] .= chr(floor($patch_array[$i]['points'][$j] % 256));
}
$count_cols = count($patch_array[$i]['colors']);
for ($j=0; $j < $count_cols; ++$j) {
$this->gradients[$n]['stream'] .= chr($patch_array[$i]['colors'][$j]['r']);
$this->gradients[$n]['stream'] .= chr($patch_array[$i]['colors'][$j]['g']);
$this->gradients[$n]['stream'] .= chr($patch_array[$i]['colors'][$j]['b']);
}
}
$this->_out('/Sh'.$n.' sh');
$this->_outRestoreGraphicsState();
if ($this->inxobj) {
$this->xobjects[$this->xobjid]['gradients'][$n] = $this->gradients[$n];
}
}
protected function Clip($x, $y, $w, $h) {
if ($this->state != 2) {
return;
}
if ($this->rtl) {
$x = $this->w - $x - $w;
}
$s = 'q';
$s .= sprintf(' %F %F %F %F re W n', $x*$this->k, ($this->h-$y)*$this->k, $w*$this->k, -$h*$this->k);
$s .= sprintf(' %F 0 0 %F %F %F cm', $w*$this->k, $h*$this->k, $x*$this->k, ($this->h-($y+$h))*$this->k);
$this->_out($s);
}
public function Gradient($type, $coords, $stops, $background=array(), $antialias=false) {
if ($this->pdfa_mode OR ($this->state != 2)) {
return;
}
$n = count($this->gradients) + 1;
$this->gradients[$n] = array();
$this->gradients[$n]['type'] = $type;
$this->gradients[$n]['coords'] = $coords;
$this->gradients[$n]['antialias'] = $antialias;
$this->gradients[$n]['colors'] = array();
$this->gradients[$n]['transparency'] = false;
$numcolspace = count($stops[0]['color']);
$bcolor = array_values($background);
switch($numcolspace) {
case 5:
case 4: {
$this->gradients[$n]['colspace'] = 'DeviceCMYK';
if (!empty($background)) {
$this->gradients[$n]['background'] = sprintf('%F %F %F %F', $bcolor[0]/100, $bcolor[1]/100, $bcolor[2]/100, $bcolor[3]/100);
}
break;
}
case 3: {
$this->gradients[$n]['colspace'] = 'DeviceRGB';
if (!empty($background)) {
$this->gradients[$n]['background'] = sprintf('%F %F %F', $bcolor[0]/255, $bcolor[1]/255, $bcolor[2]/255);
}
break;
}
case 1: {
$this->gradients[$n]['colspace'] = 'DeviceGray';
if (!empty($background)) {
$this->gradients[$n]['background'] = sprintf('%F', $bcolor[0]/255);
}
break;
}
}
$num_stops = count($stops);
$last_stop_id = $num_stops - 1;
foreach ($stops as $key => $stop) {
$this->gradients[$n]['colors'][$key] = array();
if (isset($stop['offset'])) {
$this->gradients[$n]['colors'][$key]['offset'] = $stop['offset'];
} else {
if ($key == 0) {
$this->gradients[$n]['colors'][$key]['offset'] = 0;
} elseif ($key == $last_stop_id) {
$this->gradients[$n]['colors'][$key]['offset'] = 1;
} else {
$offsetstep = (1 - $this->gradients[$n]['colors'][($key - 1)]['offset']) / ($num_stops - $key);
$this->gradients[$n]['colors'][$key]['offset'] = $this->gradients[$n]['colors'][($key - 1)]['offset'] + $offsetstep;
}
}
if (isset($stop['opacity'])) {
$this->gradients[$n]['colors'][$key]['opacity'] = $stop['opacity'];
if ((!$this->pdfa_mode) AND ($stop['opacity'] < 1)) {
$this->gradients[$n]['transparency'] = true;
}
} else {
$this->gradients[$n]['colors'][$key]['opacity'] = 1;
}
if (isset($stop['exponent'])) {
$this->gradients[$n]['colors'][$key]['exponent'] = $stop['exponent'];
} else {
$this->gradients[$n]['colors'][$key]['exponent'] = 1;
}
$color = array_values($stop['color']);
switch($numcolspace) {
case 5:
case 4: {
$this->gradients[$n]['colors'][$key]['color'] = sprintf('%F %F %F %F', $color[0]/100, $color[1]/100, $color[2]/100, $color[3]/100);
break;
}
case 3: {
$this->gradients[$n]['colors'][$key]['color'] = sprintf('%F %F %F', $color[0]/255, $color[1]/255, $color[2]/255);
break;
}
case 1: {
$this->gradients[$n]['colors'][$key]['color'] = sprintf('%F', $color[0]/255);
break;
}
}
}
if ($this->gradients[$n]['transparency']) {
$this->_out('/TGS'.$n.' gs');
}
$this->_out('/Sh'.$n.' sh');
$this->_outRestoreGraphicsState();
if ($this->inxobj) {
$this->xobjects[$this->xobjid]['gradients'][$n] = $this->gradients[$n];
}
}
function _putshaders() {
if ($this->pdfa_mode) {
return;
}
$idt = count($this->gradients);
foreach ($this->gradients as $id => $grad) {
if (($grad['type'] == 2) OR ($grad['type'] == 3)) {
$fc = $this->_newobj();
$out = '<<';
$out .= ' /FunctionType 3';
$out .= ' /Domain [0 1]';
$functions = '';
$bounds = '';
$encode = '';
$i = 1;
$num_cols = count($grad['colors']);
$lastcols = $num_cols - 1;
for ($i = 1; $i < $num_cols; ++$i) {
$functions .= ($fc + $i).' 0 R ';
if ($i < $lastcols) {
$bounds .= sprintf('%F ', $grad['colors'][$i]['offset']);
}
$encode .= '0 1 ';
}
$out .= ' /Functions ['.trim($functions).']';
$out .= ' /Bounds ['.trim($bounds).']';
$out .= ' /Encode ['.trim($encode).']';
$out .= ' >>';
$out .= "\n".'endobj';
$this->_out($out);
for ($i = 1; $i < $num_cols; ++$i) {
$this->_newobj();
$out = '<<';
$out .= ' /FunctionType 2';
$out .= ' /Domain [0 1]';
$out .= ' /C0 ['.$grad['colors'][($i - 1)]['color'].']';
$out .= ' /C1 ['.$grad['colors'][$i]['color'].']';
$out .= ' /N '.$grad['colors'][$i]['exponent'];
$out .= ' >>';
$out .= "\n".'endobj';
$this->_out($out);
}
if ($grad['transparency']) {
$ft = $this->_newobj();
$out = '<<';
$out .= ' /FunctionType 3';
$out .= ' /Domain [0 1]';
$functions = '';
$i = 1;
$num_cols = count($grad['colors']);
for ($i = 1; $i < $num_cols; ++$i) {
$functions .= ($ft + $i).' 0 R ';
}
$out .= ' /Functions ['.trim($functions).']';
$out .= ' /Bounds ['.trim($bounds).']';
$out .= ' /Encode ['.trim($encode).']';
$out .= ' >>';
$out .= "\n".'endobj';
$this->_out($out);
for ($i = 1; $i < $num_cols; ++$i) {
$this->_newobj();
$out = '<<';
$out .= ' /FunctionType 2';
$out .= ' /Domain [0 1]';
$out .= ' /C0 ['.$grad['colors'][($i - 1)]['opacity'].']';
$out .= ' /C1 ['.$grad['colors'][$i]['opacity'].']';
$out .= ' /N '.$grad['colors'][$i]['exponent'];
$out .= ' >>';
$out .= "\n".'endobj';
$this->_out($out);
}
}
}
$this->_newobj();
$out = '<< /ShadingType '.$grad['type'];
if (isset($grad['colspace'])) {
$out .= ' /ColorSpace /'.$grad['colspace'];
} else {
$out .= ' /ColorSpace /DeviceRGB';
}
if (isset($grad['background']) AND !empty($grad['background'])) {
$out .= ' /Background ['.$grad['background'].']';
}
if (isset($grad['antialias']) AND ($grad['antialias'] === true)) {
$out .= ' /AntiAlias true';
}
if ($grad['type'] == 2) {
$out .= ' '.sprintf('/Coords [%F %F %F %F]', $grad['coords'][0], $grad['coords'][1], $grad['coords'][2], $grad['coords'][3]);
$out .= ' /Domain [0 1]';
$out .= ' /Function '.$fc.' 0 R';
$out .= ' /Extend [true true]';
$out .= ' >>';
} elseif ($grad['type'] == 3) {
$out .= ' '.sprintf('/Coords [%F %F 0 %F %F %F]', $grad['coords'][0], $grad['coords'][1], $grad['coords'][2], $grad['coords'][3], $grad['coords'][4]);
$out .= ' /Domain [0 1]';
$out .= ' /Function '.$fc.' 0 R';
$out .= ' /Extend [true true]';
$out .= ' >>';
} elseif ($grad['type'] == 6) {
$out .= ' /BitsPerCoordinate 16';
$out .= ' /BitsPerComponent 8';
$out .= ' /Decode[0 1 0 1 0 1 0 1 0 1]';
$out .= ' /BitsPerFlag 8';
$stream = $this->_getrawstream($grad['stream']);
$out .= ' /Length '.strlen($stream);
$out .= ' >>';
$out .= ' stream'."\n".$stream."\n".'endstream';
}
$out .= "\n".'endobj';
$this->_out($out);
if ($grad['transparency']) {
$shading_transparency = preg_replace('/\/ColorSpace \/[^\s]+/si', '/ColorSpace /DeviceGray', $out);
$shading_transparency = preg_replace('/\/Function [0-9]+ /si', '/Function '.$ft.' ', $shading_transparency);
}
$this->gradients[$id]['id'] = $this->n;
$this->_newobj();
$out = '<< /Type /Pattern /PatternType 2';
$out .= ' /Shading '.$this->gradients[$id]['id'].' 0 R';
$out .= ' >>';
$out .= "\n".'endobj';
$this->_out($out);
$this->gradients[$id]['pattern'] = $this->n;
if ($grad['transparency']) {
$idgs = $id + $idt;
$this->_newobj();
$this->_out($shading_transparency);
$this->gradients[$idgs]['id'] = $this->n;
$this->_newobj();
$out = '<< /Type /Pattern /PatternType 2';
$out .= ' /Shading '.$this->gradients[$idgs]['id'].' 0 R';
$out .= ' >>';
$out .= "\n".'endobj';
$this->_out($out);
$this->gradients[$idgs]['pattern'] = $this->n;
$oid = $this->_newobj();
$this->xobjects['LX'.$oid] = array('n' => $oid);
$filter = '';
$stream = 'q /a0 gs /Pattern cs /p'.$idgs.' scn 0 0 '.$this->wPt.' '.$this->hPt.' re f Q';
if ($this->compress) {
$filter = ' /Filter /FlateDecode';
$stream = gzcompress($stream);
}
$stream = $this->_getrawstream($stream);
$out = '<< /Type /XObject /Subtype /Form /FormType 1'.$filter;
$out .= ' /Length '.strlen($stream);
$rect = sprintf('%F %F', $this->wPt, $this->hPt);
$out .= ' /BBox [0 0 '.$rect.']';
$out .= ' /Group << /Type /Group /S /Transparency /CS /DeviceGray >>';
$out .= ' /Resources <<';
$out .= ' /ExtGState << /a0 << /ca 1 /CA 1 >> >>';
$out .= ' /Pattern << /p'.$idgs.' '.$this->gradients[$idgs]['pattern'].' 0 R >>';
$out .= ' >>';
$out .= ' >> ';
$out .= ' stream'."\n".$stream."\n".'endstream';
$out .= "\n".'endobj';
$this->_out($out);
$this->_newobj();
$out = '<< /Type /Mask /S /Luminosity /G '.($this->n - 1).' 0 R >>'."\n".'endobj';
$this->_out($out);
$this->_newobj();
$out = '<< /Type /ExtGState /SMask '.($this->n - 1).' 0 R /AIS false >>'."\n".'endobj';
$this->_out($out);
$this->extgstates[] = array('n' => $this->n, 'name' => 'TGS'.$id);
}
}
}
public function PieSector($xc, $yc, $r, $a, $b, $style='FD', $cw=true, $o=90) {
$this->PieSectorXY($xc, $yc, $r, $r, $a, $b, $style, $cw, $o);
}
public function PieSectorXY($xc, $yc, $rx, $ry, $a, $b, $style='FD', $cw=false, $o=0, $nc=2) {
if ($this->state != 2) {
return;
}
if ($this->rtl) {
$xc = ($this->w - $xc);
}
$op = TCPDF_STATIC::getPathPaintOperator($style);
if ($op == 'f') {
$line_style = array();
}
if ($cw) {
$d = $b;
$b = (360 - $a + $o);
$a = (360 - $d + $o);
} else {
$b += $o;
$a += $o;
}
$this->_outellipticalarc($xc, $yc, $rx, $ry, 0, $a, $b, true, $nc);
$this->_out($op);
}
public function ImageEps($file, $x='', $y='', $w=0, $h=0, $link='', $useBoundingBox=true, $align='', $palign='', $border=0, $fitonpage=false, $fixoutvals=false) {
if ($this->state != 2) {
return;
}
if ($this->rasterize_vector_images AND ($w > 0) AND ($h > 0)) {
return $this->Image($file, $x, $y, $w, $h, 'EPS', $link, $align, true, 300, $palign, false, false, $border, false, false, $fitonpage);
}
if ($x === '') {
$x = $this->x;
}
if ($y === '') {
$y = $this->y;
}
list($x, $y) = $this->checkPageRegions($h, $x, $y);
$k = $this->k;
if ($file[0] === '@') {
$data = substr($file, 1);
} else {
$data = TCPDF_STATIC::fileGetContents($file);
}
if ($data === FALSE) {
$this->Error('EPS file not found: '.$file);
}
$regs = array();
preg_match("/%%Creator:([^\r\n]+)/", $data, $regs);
if (count($regs) > 1) {
$version_str = trim($regs[1]);
if (strpos($version_str, 'Adobe Illustrator') !== false) {
$versexp = explode(' ', $version_str);
$version = (float)array_pop($versexp);
if ($version >= 9) {
$this->Error('This version of Adobe Illustrator file is not supported: '.$file);
}
}
}
$start = strpos($data, '%!PS-Adobe');
if ($start > 0) {
$data = substr($data, $start);
}
preg_match("/%%BoundingBox:([^\r\n]+)/", $data, $regs);
if (count($regs) > 1) {
list($x1, $y1, $x2, $y2) = explode(' ', trim($regs[1]));
} else {
$this->Error('No BoundingBox found in EPS/AI file: '.$file);
}
$start = strpos($data, '%%EndSetup');
if ($start === false) {
$start = strpos($data, '%%EndProlog');
}
if ($start === false) {
$start = strpos($data, '%%BoundingBox');
}
$data = substr($data, $start);
$end = strpos($data, '%%PageTrailer');
if ($end===false) {
$end = strpos($data, 'showpage');
}
if ($end) {
$data = substr($data, 0, $end);
}
if (($w <= 0) AND ($h <= 0)) {
$w = ($x2 - $x1) / $k;
$h = ($y2 - $y1) / $k;
} elseif ($w <= 0) {
$w = ($x2-$x1) / $k * ($h / (($y2 - $y1) / $k));
} elseif ($h <= 0) {
$h = ($y2 - $y1) / $k * ($w / (($x2 - $x1) / $k));
}
list($w, $h, $x, $y) = $this->fitBlock($w, $h, $x, $y, $fitonpage);
if ($this->rasterize_vector_images) {
return $this->Image($file, $x, $y, $w, $h, 'EPS', $link, $align, true, 300, $palign, false, false, $border, false, false, $fitonpage);
}
$scale_x = $w / (($x2 - $x1) / $k);
$scale_y = $h / (($y2 - $y1) / $k);
$this->img_rb_y = $y + $h;
if ($this->rtl) {
if ($palign == 'L') {
$ximg = $this->lMargin;
} elseif ($palign == 'C') {
$ximg = ($this->w + $this->lMargin - $this->rMargin - $w) / 2;
} elseif ($palign == 'R') {
$ximg = $this->w - $this->rMargin - $w;
} else {
$ximg = $x - $w;
}
$this->img_rb_x = $ximg;
} else {
if ($palign == 'L') {
$ximg = $this->lMargin;
} elseif ($palign == 'C') {
$ximg = ($this->w + $this->lMargin - $this->rMargin - $w) / 2;
} elseif ($palign == 'R') {
$ximg = $this->w - $this->rMargin - $w;
} else {
$ximg = $x;
}
$this->img_rb_x = $ximg + $w;
}
if ($useBoundingBox) {
$dx = $ximg * $k - $x1;
$dy = $y * $k - $y1;
} else {
$dx = $ximg * $k;
$dy = $y * $k;
}
$this->_out('q'.$this->epsmarker);
$this->_out(sprintf('%F %F %F %F %F %F cm', 1, 0, 0, 1, $dx, $dy + ($this->hPt - (2 * $y * $k) - ($y2 - $y1))));
if (isset($scale_x)) {
$this->_out(sprintf('%F %F %F %F %F %F cm', $scale_x, 0, 0, $scale_y, $x1 * (1 - $scale_x), $y2 * (1 - $scale_y)));
}
$lines = preg_split('/[\r\n]+/si', $data, -1, PREG_SPLIT_NO_EMPTY);
$u=0;
$cnt = count($lines);
for ($i=0; $i < $cnt; ++$i) {
$line = $lines[$i];
if (($line == '') OR ($line[0] == '%')) {
continue;
}
$len = strlen($line);
$color_name = '';
if (strcasecmp('x', substr(trim($line), -1)) == 0) {
if (preg_match('/\([^\)]*\)/', $line, $matches) > 0) {
$color_name = $matches[0];
$line = str_replace(' '.$color_name, '', $line);
$color_name = substr($color_name, 1, -1);
}
}
$chunks = explode(' ', $line);
$cmd = trim(array_pop($chunks));
if (($cmd == 'Xa') OR ($cmd == 'XA')) {
$b = array_pop($chunks);
$g = array_pop($chunks);
$r = array_pop($chunks);
$this->_out(''.$r.' '.$g.' '.$b.' '.($cmd=='Xa'?'rg':'RG'));
continue;
}
$skip = false;
if ($fixoutvals) {
switch ($cmd) {
case 'm':
case 'l':
case 'L': {
foreach ($chunks as $key => $val) {
if ((($key % 2) == 0) AND (($val < $x1) OR ($val > $x2))) {
$skip = true;
} elseif ((($key % 2) != 0) AND (($val < $y1) OR ($val > $y2))) {
$skip = true;
}
}
}
}
}
switch ($cmd) {
case 'm':
case 'l':
case 'v':
case 'y':
case 'c':
case 'k':
case 'K':
case 'g':
case 'G':
case 's':
case 'S':
case 'J':
case 'j':
case 'w':
case 'M':
case 'd':
case 'n': {
if ($skip) {
break;
}
$this->_out($line);
break;
}
case 'x': {
if (empty($color_name)) {
list($col_c, $col_m, $col_y, $col_k) = $chunks;
$this->_out(''.$col_c.' '.$col_m.' '.$col_y.' '.$col_k.' k');
} else {
list($col_c, $col_m, $col_y, $col_k, $col_t) = $chunks;
$this->AddSpotColor($color_name, ($col_c * 100), ($col_m * 100), ($col_y * 100), ($col_k * 100));
$color_cmd = sprintf('/CS%d cs %F scn', $this->spot_colors[$color_name]['i'], (1 - $col_t));
$this->_out($color_cmd);
}
break;
}
case 'X': {
if (empty($color_name)) {
list($col_c, $col_m, $col_y, $col_k) = $chunks;
$this->_out(''.$col_c.' '.$col_m.' '.$col_y.' '.$col_k.' K');
} else {
list($col_c, $col_m, $col_y, $col_k, $col_t) = $chunks;
$this->AddSpotColor($color_name, ($col_c * 100), ($col_m * 100), ($col_y * 100), ($col_k * 100));
$color_cmd = sprintf('/CS%d CS %F SCN', $this->spot_colors[$color_name]['i'], (1 - $col_t));
$this->_out($color_cmd);
}
break;
}
case 'Y':
case 'N':
case 'V':
case 'L':
case 'C': {
if ($skip) {
break;
}
$line[($len - 1)] = strtolower($cmd);
$this->_out($line);
break;
}
case 'b':
case 'B': {
$this->_out($cmd . '*');
break;
}
case 'f':
case 'F': {
if ($u > 0) {
$isU = false;
$max = min(($i + 5), $cnt);
for ($j = ($i + 1); $j < $max; ++$j) {
$isU = ($isU OR (($lines[$j] == 'U') OR ($lines[$j] == '*U')));
}
if ($isU) {
$this->_out('f*');
}
} else {
$this->_out('f*');
}
break;
}
case '*u': {
++$u;
break;
}
case '*U': {
--$u;
break;
}
}
}
$this->_out($this->epsmarker.'Q');
if (!empty($border)) {
$bx = $this->x;
$by = $this->y;
$this->x = $ximg;
if ($this->rtl) {
$this->x += $w;
}
$this->y = $y;
$this->Cell($w, $h, '', $border, 0, '', 0, '', 0, true);
$this->x = $bx;
$this->y = $by;
}
if ($link) {
$this->Link($ximg, $y, $w, $h, $link, 0);
}
switch($align) {
case 'T':{
$this->y = $y;
$this->x = $this->img_rb_x;
break;
}
case 'M':{
$this->y = $y + round($h/2);
$this->x = $this->img_rb_x;
break;
}
case 'B':{
$this->y = $this->img_rb_y;
$this->x = $this->img_rb_x;
break;
}
case 'N':{
$this->SetY($this->img_rb_y);
break;
}
default:{
break;
}
}
$this->endlinex = $this->img_rb_x;
}
public function setBarcode($bc='') {
$this->barcode = $bc;
}
public function getBarcode() {
return $this->barcode;
}
public function write1DBarcode($code, $type, $x='', $y='', $w='', $h='', $xres='', $style=array(), $align='') {
if (TCPDF_STATIC::empty_string(trim($code))) {
return;
}
require_once(dirname(__FILE__).'/tcpdf_barcodes_1d.php');
$gvars = $this->getGraphicVars();
$barcodeobj = new TCPDFBarcode($code, $type);
$arrcode = $barcodeobj->getBarcodeArray();
if (($arrcode === false) OR empty($arrcode) OR ($arrcode['maxw'] <= 0)) {
$this->Error('Error in 1D barcode string');
}
if ($arrcode['maxh'] <= 0) {
$arrcode['maxh'] = 1;
}
if (!isset($style['position'])) {
$style['position'] = '';
} elseif ($style['position'] == 'S') {
$style['position'] = '';
$style['stretch'] = true;
}
if (!isset($style['fitwidth'])) {
if (!isset($style['stretch'])) {
$style['fitwidth'] = true;
} else {
$style['fitwidth'] = false;
}
}
if ($style['fitwidth']) {
$style['stretch'] = false;
}
if (!isset($style['stretch'])) {
if (($w === '') OR ($w <= 0)) {
$style['stretch'] = false;
} else {
$style['stretch'] = true;
}
}
if (!isset($style['fgcolor'])) {
$style['fgcolor'] = array(0,0,0);
}
if (!isset($style['bgcolor'])) {
$style['bgcolor'] = false;
}
if (!isset($style['border'])) {
$style['border'] = false;
}
$fontsize = 0;
if (!isset($style['text'])) {
$style['text'] = false;
}
if ($style['text'] AND isset($style['font'])) {
if (isset($style['fontsize'])) {
$fontsize = $style['fontsize'];
}
$this->SetFont($style['font'], '', $fontsize);
}
if (!isset($style['stretchtext'])) {
$style['stretchtext'] = 4;
}
if ($x === '') {
$x = $this->x;
}
if ($y === '') {
$y = $this->y;
}
list($x, $y) = $this->checkPageRegions($h, $x, $y);
if (($w === '') OR ($w <= 0)) {
if ($this->rtl) {
$w = $x - $this->lMargin;
} else {
$w = $this->w - $this->rMargin - $x;
}
}
if (!isset($style['padding'])) {
$padding = 0;
} elseif ($style['padding'] === 'auto') {
$padding = 10 * ($w / ($arrcode['maxw'] + 20));
} else {
$padding = floatval($style['padding']);
}
if (!isset($style['hpadding'])) {
$hpadding = $padding;
} elseif ($style['hpadding'] === 'auto') {
$hpadding = 10 * ($w / ($arrcode['maxw'] + 20));
} else {
$hpadding = floatval($style['hpadding']);
}
if (!isset($style['vpadding'])) {
$vpadding = $padding;
} elseif ($style['vpadding'] === 'auto') {
$vpadding = ($hpadding / 2);
} else {
$vpadding = floatval($style['vpadding']);
}
$max_xres = ($w - (2 * $hpadding)) / $arrcode['maxw'];
if ($style['stretch']) {
$xres = $max_xres;
} else {
if (TCPDF_STATIC::empty_string($xres)) {
$xres = (0.141 * $this->k);
}
if ($xres > $max_xres) {
$xres = $max_xres;
}
if ((isset($style['padding']) AND ($style['padding'] === 'auto'))
OR (isset($style['hpadding']) AND ($style['hpadding'] === 'auto'))) {
$hpadding = 10 * $xres;
if (isset($style['vpadding']) AND ($style['vpadding'] === 'auto')) {
$vpadding = ($hpadding / 2);
}
}
}
if ($style['fitwidth']) {
$wold = $w;
$w = (($arrcode['maxw'] * $xres) + (2 * $hpadding));
if (isset($style['cellfitalign'])) {
switch ($style['cellfitalign']) {
case 'L': {
if ($this->rtl) {
$x -= ($wold - $w);
}
break;
}
case 'R': {
if (!$this->rtl) {
$x += ($wold - $w);
}
break;
}
case 'C': {
if ($this->rtl) {
$x -= (($wold - $w) / 2);
} else {
$x += (($wold - $w) / 2);
}
break;
}
default : {
break;
}
}
}
}
$text_height = $this->getCellHeight($fontsize / $this->k);
if (($h === '') OR ($h <= 0)) {
$h = (($arrcode['maxw'] * $xres) / 3) + (2 * $vpadding) + $text_height;
}
$barh = $h - $text_height - (2 * $vpadding);
if ($barh <=0) {
if ($text_height > $h) {
$fontsize = (($h * $this->k) / (4 * $this->cell_height_ratio));
$text_height = $this->getCellHeight($fontsize / $this->k);
$this->SetFont($style['font'], '', $fontsize);
}
if ($vpadding > 0) {
$vpadding = (($h - $text_height) / 4);
}
$barh = $h - $text_height - (2 * $vpadding);
}
list($w, $h, $x, $y) = $this->fitBlock($w, $h, $x, $y, false);
$this->img_rb_y = $y + $h;
if ($this->rtl) {
if ($style['position'] == 'L') {
$xpos = $this->lMargin;
} elseif ($style['position'] == 'C') {
$xpos = ($this->w + $this->lMargin - $this->rMargin - $w) / 2;
} elseif ($style['position'] == 'R') {
$xpos = $this->w - $this->rMargin - $w;
} else {
$xpos = $x - $w;
}
$this->img_rb_x = $xpos;
} else {
if ($style['position'] == 'L') {
$xpos = $this->lMargin;
} elseif ($style['position'] == 'C') {
$xpos = ($this->w + $this->lMargin - $this->rMargin - $w) / 2;
} elseif ($style['position'] == 'R') {
$xpos = $this->w - $this->rMargin - $w;
} else {
$xpos = $x;
}
$this->img_rb_x = $xpos + $w;
}
$xpos_rect = $xpos;
if (!isset($style['align'])) {
$style['align'] = 'C';
}
switch ($style['align']) {
case 'L': {
$xpos = $xpos_rect + $hpadding;
break;
}
case 'R': {
$xpos = $xpos_rect + ($w - ($arrcode['maxw'] * $xres)) - $hpadding;
break;
}
case 'C':
default : {
$xpos = $xpos_rect + (($w - ($arrcode['maxw'] * $xres)) / 2);
break;
}
}
$xpos_text = $xpos;
$tempRTL = $this->rtl;
$this->rtl = false;
if ($style['bgcolor']) {
$this->Rect($xpos_rect, $y, $w, $h, $style['border'] ? 'DF' : 'F', '', $style['bgcolor']);
} elseif ($style['border']) {
$this->Rect($xpos_rect, $y, $w, $h, 'D');
}
$this->SetDrawColorArray($style['fgcolor']);
$this->SetTextColorArray($style['fgcolor']);
foreach ($arrcode['bcode'] as $k => $v) {
$bw = ($v['w'] * $xres);
if ($v['t']) {
$ypos = $y + $vpadding + ($v['p'] * $barh / $arrcode['maxh']);
$this->Rect($xpos, $ypos, $bw, ($v['h'] * $barh / $arrcode['maxh']), 'F', array(), $style['fgcolor']);
}
$xpos += $bw;
}
if ($style['text']) {
if (isset($style['label']) AND !TCPDF_STATIC::empty_string($style['label'])) {
$label = $style['label'];
} else {
$label = $code;
}
$txtwidth = ($arrcode['maxw'] * $xres);
if ($this->GetStringWidth($label) > $txtwidth) {
$style['stretchtext'] = 2;
}
$this->x = $xpos_text;
$this->y = $y + $vpadding + $barh;
$cellpadding = $this->cell_padding;
$this->SetCellPadding(0);
$this->Cell($txtwidth, '', $label, 0, 0, 'C', false, '', $style['stretchtext'], false, 'T', 'T');
$this->cell_padding = $cellpadding;
}
$this->rtl = $tempRTL;
$this->setGraphicVars($gvars);
switch($align) {
case 'T':{
$this->y = $y;
$this->x = $this->img_rb_x;
break;
}
case 'M':{
$this->y = $y + round($h / 2);
$this->x = $this->img_rb_x;
break;
}
case 'B':{
$this->y = $this->img_rb_y;
$this->x = $this->img_rb_x;
break;
}
case 'N':{
$this->SetY($this->img_rb_y);
break;
}
default:{
break;
}
}
$this->endlinex = $this->img_rb_x;
}
public function write2DBarcode($code, $type, $x='', $y='', $w='', $h='', $style=array(), $align='', $distort=false) {
if (TCPDF_STATIC::empty_string(trim($code))) {
return;
}
require_once(dirname(__FILE__).'/tcpdf_barcodes_2d.php');
$gvars = $this->getGraphicVars();
$barcodeobj = new TCPDF2DBarcode($code, $type);
$arrcode = $barcodeobj->getBarcodeArray();
if (($arrcode === false) OR empty($arrcode) OR !isset($arrcode['num_rows']) OR ($arrcode['num_rows'] == 0) OR !isset($arrcode['num_cols']) OR ($arrcode['num_cols'] == 0)) {
$this->Error('Error in 2D barcode string');
}
if (!isset($style['position'])) {
$style['position'] = '';
}
if (!isset($style['fgcolor'])) {
$style['fgcolor'] = array(0,0,0);
}
if (!isset($style['bgcolor'])) {
$style['bgcolor'] = false;
}
if (!isset($style['border'])) {
$style['border'] = false;
}
if (!isset($style['padding'])) {
$style['padding'] = 0;
} elseif ($style['padding'] === 'auto') {
$style['padding'] = 4;
}
if (!isset($style['hpadding'])) {
$style['hpadding'] = $style['padding'];
} elseif ($style['hpadding'] === 'auto') {
$style['hpadding'] = 4;
}
if (!isset($style['vpadding'])) {
$style['vpadding'] = $style['padding'];
} elseif ($style['vpadding'] === 'auto') {
$style['vpadding'] = 4;
}
$hpad = (2 * $style['hpadding']);
$vpad = (2 * $style['vpadding']);
if (!isset($style['module_width'])) {
$style['module_width'] = 1;
}
if (!isset($style['module_height'])) {
$style['module_height'] = 1;
}
if ($x === '') {
$x = $this->x;
}
if ($y === '') {
$y = $this->y;
}
list($x, $y) = $this->checkPageRegions($h, $x, $y);
$rows = $arrcode['num_rows'];
$cols = $arrcode['num_cols'];
if (($rows <= 0) || ($cols <= 0)){
$this->Error('Error in 2D barcode string');
}
$mw = $style['module_width'];
$mh = $style['module_height'];
if (($mw <= 0) OR ($mh <= 0)) {
$this->Error('Error in 2D barcode string');
}
if ($this->rtl) {
$maxw = $x - $this->lMargin;
} else {
$maxw = $this->w - $this->rMargin - $x;
}
$maxh = ($this->h - $this->tMargin - $this->bMargin);
$ratioHW = ((($rows * $mh) + $hpad) / (($cols * $mw) + $vpad));
$ratioWH = ((($cols * $mw) + $vpad) / (($rows * $mh) + $hpad));
if (!$distort) {
if (($maxw * $ratioHW) > $maxh) {
$maxw = $maxh * $ratioWH;
}
if (($maxh * $ratioWH) > $maxw) {
$maxh = $maxw * $ratioHW;
}
}
if ($w > $maxw) {
$w = $maxw;
}
if ($h > $maxh) {
$h = $maxh;
}
if ((($w === '') OR ($w <= 0)) AND (($h === '') OR ($h <= 0))) {
$w = ($cols + $hpad) * ($mw / $this->k);
$h = ($rows + $vpad) * ($mh / $this->k);
} elseif (($w === '') OR ($w <= 0)) {
$w = $h * $ratioWH;
} elseif (($h === '') OR ($h <= 0)) {
$h = $w * $ratioHW;
}
$bw = ($w * $cols) / ($cols + $hpad);
$bh = ($h * $rows) / ($rows + $vpad);
$cw = $bw / $cols;
$ch = $bh / $rows;
if (!$distort) {
if (($cw / $ch) > ($mw / $mh)) {
$cw = $ch * $mw / $mh;
$bw = $cw * $cols;
$style['hpadding'] = ($w - $bw) / (2 * $cw);
} else {
$ch = $cw * $mh / $mw;
$bh = $ch * $rows;
$style['vpadding'] = ($h - $bh) / (2 * $ch);
}
}
list($w, $h, $x, $y) = $this->fitBlock($w, $h, $x, $y, false);
$this->img_rb_y = $y + $h;
if ($this->rtl) {
if ($style['position'] == 'L') {
$xpos = $this->lMargin;
} elseif ($style['position'] == 'C') {
$xpos = ($this->w + $this->lMargin - $this->rMargin - $w) / 2;
} elseif ($style['position'] == 'R') {
$xpos = $this->w - $this->rMargin - $w;
} else {
$xpos = $x - $w;
}
$this->img_rb_x = $xpos;
} else {
if ($style['position'] == 'L') {
$xpos = $this->lMargin;
} elseif ($style['position'] == 'C') {
$xpos = ($this->w + $this->lMargin - $this->rMargin - $w) / 2;
} elseif ($style['position'] == 'R') {
$xpos = $this->w - $this->rMargin - $w;
} else {
$xpos = $x;
}
$this->img_rb_x = $xpos + $w;
}
$xstart = $xpos + ($style['hpadding'] * $cw);
$ystart = $y + ($style['vpadding'] * $ch);
$tempRTL = $this->rtl;
$this->rtl = false;
if ($style['bgcolor']) {
$this->Rect($xpos, $y, $w, $h, $style['border'] ? 'DF' : 'F', '', $style['bgcolor']);
} elseif ($style['border']) {
$this->Rect($xpos, $y, $w, $h, 'D');
}
$this->SetDrawColorArray($style['fgcolor']);
for ($r = 0; $r < $rows; ++$r) {
$xr = $xstart;
for ($c = 0; $c < $cols; ++$c) {
if ($arrcode['bcode'][$r][$c] == 1) {
$this->Rect($xr, $ystart, $cw, $ch, 'F', array(), $style['fgcolor']);
}
$xr += $cw;
}
$ystart += $ch;
}
$this->rtl = $tempRTL;
$this->setGraphicVars($gvars);
switch($align) {
case 'T':{
$this->y = $y;
$this->x = $this->img_rb_x;
break;
}
case 'M':{
$this->y = $y + round($h/2);
$this->x = $this->img_rb_x;
break;
}
case 'B':{
$this->y = $this->img_rb_y;
$this->x = $this->img_rb_x;
break;
}
case 'N':{
$this->SetY($this->img_rb_y);
break;
}
default:{
break;
}
}
$this->endlinex = $this->img_rb_x;
}
public function getMargins() {
$ret = array(
'left' => $this->lMargin,
'right' => $this->rMargin,
'top' => $this->tMargin,
'bottom' => $this->bMargin,
'header' => $this->header_margin,
'footer' => $this->footer_margin,
'cell' => $this->cell_padding,
'padding_left' => $this->cell_padding['L'],
'padding_top' => $this->cell_padding['T'],
'padding_right' => $this->cell_padding['R'],
'padding_bottom' => $this->cell_padding['B']
);
return $ret;
}
public function getOriginalMargins() {
$ret = array(
'left' => $this->original_lMargin,
'right' => $this->original_rMargin
);
return $ret;
}
public function getFontSize() {
return $this->FontSize;
}
public function getFontSizePt() {
return $this->FontSizePt;
}
public function getFontFamily() {
return $this->FontFamily;
}
public function getFontStyle() {
return $this->FontStyle;
}
public function fixHTMLCode($html, $default_css='', $tagvs='', $tidy_options='') {
return TCPDF_STATIC::fixHTMLCode($html, $default_css, $tagvs, $tidy_options, $this->tagvspaces);
}
protected function getCSSBorderWidth($width) {
if ($width == 'thin') {
$width = (2 / $this->k);
} elseif ($width == 'medium') {
$width = (4 / $this->k);
} elseif ($width == 'thick') {
$width = (6 / $this->k);
} else {
$width = $this->getHTMLUnitToUnits($width, 1, 'px', false);
}
return $width;
}
protected function getCSSBorderDashStyle($style) {
switch (strtolower($style)) {
case 'none':
case 'hidden': {
$dash = -1;
break;
}
case 'dotted': {
$dash = 1;
break;
}
case 'dashed': {
$dash = 3;
break;
}
case 'double':
case 'groove':
case 'ridge':
case 'inset':
case 'outset':
case 'solid':
default: {
$dash = 0;
break;
}
}
return $dash;
}
protected function getCSSBorderStyle($cssborder) {
$bprop = preg_split('/[\s]+/', trim($cssborder));
$border = array();
switch (count($bprop)) {
case 3: {
$width = $bprop[0];
$style = $bprop[1];
$color = $bprop[2];
break;
}
case 2: {
$width = 'medium';
$style = $bprop[0];
$color = $bprop[1];
break;
}
case 1: {
$width = 'medium';
$style = $bprop[0];
$color = 'black';
break;
}
default: {
$width = 'medium';
$style = 'solid';
$color = 'black';
break;
}
}
if ($style == 'none') {
return array();
}
$border['cap'] = 'square';
$border['join'] = 'miter';
$border['dash'] = $this->getCSSBorderDashStyle($style);
if ($border['dash'] < 0) {
return array();
}
$border['width'] = $this->getCSSBorderWidth($width);
$border['color'] = TCPDF_COLORS::convertHTMLColorToDec($color, $this->spot_colors);
return $border;
}
public function getCSSPadding($csspadding, $width=0) {
$padding = preg_split('/[\s]+/', trim($csspadding));
$cell_padding = array();
switch (count($padding)) {
case 4: {
$cell_padding['T'] = $padding[0];
$cell_padding['R'] = $padding[1];
$cell_padding['B'] = $padding[2];
$cell_padding['L'] = $padding[3];
break;
}
case 3: {
$cell_padding['T'] = $padding[0];
$cell_padding['R'] = $padding[1];
$cell_padding['B'] = $padding[2];
$cell_padding['L'] = $padding[1];
break;
}
case 2: {
$cell_padding['T'] = $padding[0];
$cell_padding['R'] = $padding[1];
$cell_padding['B'] = $padding[0];
$cell_padding['L'] = $padding[1];
break;
}
case 1: {
$cell_padding['T'] = $padding[0];
$cell_padding['R'] = $padding[0];
$cell_padding['B'] = $padding[0];
$cell_padding['L'] = $padding[0];
break;
}
default: {
return $this->cell_padding;
}
}
if ($width == 0) {
$width = $this->w - $this->lMargin - $this->rMargin;
}
$cell_padding['T'] = $this->getHTMLUnitToUnits($cell_padding['T'], $width, 'px', false);
$cell_padding['R'] = $this->getHTMLUnitToUnits($cell_padding['R'], $width, 'px', false);
$cell_padding['B'] = $this->getHTMLUnitToUnits($cell_padding['B'], $width, 'px', false);
$cell_padding['L'] = $this->getHTMLUnitToUnits($cell_padding['L'], $width, 'px', false);
return $cell_padding;
}
public function getCSSMargin($cssmargin, $width=0) {
$margin = preg_split('/[\s]+/', trim($cssmargin));
$cell_margin = array();
switch (count($margin)) {
case 4: {
$cell_margin['T'] = $margin[0];
$cell_margin['R'] = $margin[1];
$cell_margin['B'] = $margin[2];
$cell_margin['L'] = $margin[3];
break;
}
case 3: {
$cell_margin['T'] = $margin[0];
$cell_margin['R'] = $margin[1];
$cell_margin['B'] = $margin[2];
$cell_margin['L'] = $margin[1];
break;
}
case 2: {
$cell_margin['T'] = $margin[0];
$cell_margin['R'] = $margin[1];
$cell_margin['B'] = $margin[0];
$cell_margin['L'] = $margin[1];
break;
}
case 1: {
$cell_margin['T'] = $margin[0];
$cell_margin['R'] = $margin[0];
$cell_margin['B'] = $margin[0];
$cell_margin['L'] = $margin[0];
break;
}
default: {
return $this->cell_margin;
}
}
if ($width == 0) {
$width = $this->w - $this->lMargin - $this->rMargin;
}
$cell_margin['T'] = $this->getHTMLUnitToUnits(str_replace('auto', '0', $cell_margin['T']), $width, 'px', false);
$cell_margin['R'] = $this->getHTMLUnitToUnits(str_replace('auto', '0', $cell_margin['R']), $width, 'px', false);
$cell_margin['B'] = $this->getHTMLUnitToUnits(str_replace('auto', '0', $cell_margin['B']), $width, 'px', false);
$cell_margin['L'] = $this->getHTMLUnitToUnits(str_replace('auto', '0', $cell_margin['L']), $width, 'px', false);
return $cell_margin;
}
public function getCSSBorderMargin($cssbspace, $width=0) {
$space = preg_split('/[\s]+/', trim($cssbspace));
$border_spacing = array();
switch (count($space)) {
case 2: {
$border_spacing['H'] = $space[0];
$border_spacing['V'] = $space[1];
break;
}
case 1: {
$border_spacing['H'] = $space[0];
$border_spacing['V'] = $space[0];
break;
}
default: {
return array('H' => 0, 'V' => 0);
}
}
if ($width == 0) {
$width = $this->w - $this->lMargin - $this->rMargin;
}
$border_spacing['H'] = $this->getHTMLUnitToUnits($border_spacing['H'], $width, 'px', false);
$border_spacing['V'] = $this->getHTMLUnitToUnits($border_spacing['V'], $width, 'px', false);
return $border_spacing;
}
protected function getCSSFontSpacing($spacing, $parent=0) {
$val = 0;
$spacing = trim($spacing);
switch ($spacing) {
case 'normal': {
$val = 0;
break;
}
case 'inherit': {
if ($parent == 'normal') {
$val = 0;
} else {
$val = $parent;
}
break;
}
default: {
$val = $this->getHTMLUnitToUnits($spacing, 0, 'px', false);
}
}
return $val;
}
protected function getCSSFontStretching($stretch, $parent=100) {
$val = 100;
$stretch = trim($stretch);
switch ($stretch) {
case 'ultra-condensed': {
$val = 40;
break;
}
case 'extra-condensed': {
$val = 55;
break;
}
case 'condensed': {
$val = 70;
break;
}
case 'semi-condensed': {
$val = 85;
break;
}
case 'normal': {
$val = 100;
break;
}
case 'semi-expanded': {
$val = 115;
break;
}
case 'expanded': {
$val = 130;
break;
}
case 'extra-expanded': {
$val = 145;
break;
}
case 'ultra-expanded': {
$val = 160;
break;
}
case 'wider': {
$val = ($parent + 10);
break;
}
case 'narrower': {
$val = ($parent - 10);
break;
}
case 'inherit': {
if ($parent == 'normal') {
$val = 100;
} else {
$val = $parent;
}
break;
}
default: {
$val = $this->getHTMLUnitToUnits($stretch, 100, '%', false);
}
}
return $val;
}
public function getHTMLFontUnits($val, $refsize=12, $parent_size=12, $defaultunit='pt') {
$refsize = TCPDF_FONTS::getFontRefSize($refsize);
$parent_size = TCPDF_FONTS::getFontRefSize($parent_size, $refsize);
switch ($val) {
case 'xx-small': {
$size = ($refsize - 4);
break;
}
case 'x-small': {
$size = ($refsize - 3);
break;
}
case 'small': {
$size = ($refsize - 2);
break;
}
case 'medium': {
$size = $refsize;
break;
}
case 'large': {
$size = ($refsize + 2);
break;
}
case 'x-large': {
$size = ($refsize + 4);
break;
}
case 'xx-large': {
$size = ($refsize + 6);
break;
}
case 'smaller': {
$size = ($parent_size - 3);
break;
}
case 'larger': {
$size = ($parent_size + 3);
break;
}
default: {
$size = $this->getHTMLUnitToUnits($val, $parent_size, $defaultunit, true);
}
}
return $size;
}
protected function getHtmlDomArray($html) {
$css = array();
$matches = array();
if (preg_match_all('/<cssarray>([^\<]*)<\/cssarray>/isU', $html, $matches) > 0) {
if (isset($matches[1][0])) {
$css = array_merge($css, json_decode($this->unhtmlentities($matches[1][0]), true));
}
$html = preg_replace('/<cssarray>(.*?)<\/cssarray>/isU', '', $html);
}
$matches = array();
if (preg_match_all('/<link([^\>]*)>/isU', $html, $matches) > 0) {
foreach ($matches[1] as $key => $link) {
$type = array();
if (preg_match('/type[\s]*=[\s]*"text\/css"/', $link, $type)) {
$type = array();
preg_match('/media[\s]*=[\s]*"([^"]*)"/', $link, $type);
if (empty($type) OR (isset($type[1]) AND (($type[1] == 'all') OR ($type[1] == 'print')))) {
$type = array();
if (preg_match('/href[\s]*=[\s]*"([^"]*)"/', $link, $type) > 0) {
$cssdata = TCPDF_STATIC::fileGetContents(trim($type[1]));
if (($cssdata !== FALSE) AND (strlen($cssdata) > 0)) {
$css = array_merge($css, TCPDF_STATIC::extractCSSproperties($cssdata));
}
}
}
}
}
}
$matches = array();
if (preg_match_all('/<style([^\>]*)>([^\<]*)<\/style>/isU', $html, $matches) > 0) {
foreach ($matches[1] as $key => $media) {
$type = array();
preg_match('/media[\s]*=[\s]*"([^"]*)"/', $media, $type);
if (empty($type) OR (isset($type[1]) AND (($type[1] == 'all') OR ($type[1] == 'print')))) {
$cssdata = $matches[2][$key];
$css = array_merge($css, TCPDF_STATIC::extractCSSproperties($cssdata));
}
}
}
$csstagarray = '<cssarray>'.htmlentities(json_encode($css)).'</cssarray>';
$html = preg_replace('/<head([^\>]*)>(.*?)<\/head>/siU', '', $html);
$html = preg_replace('/<style([^\>]*)>([^\<]*)<\/style>/isU', '', $html);
$blocktags = array('blockquote','br','dd','dl','div','dt','h1','h2','h3','h4','h5','h6','hr','li','ol','p','pre','ul','tcpdf','table','tr','td');
$selfclosingtags = array('area','base','basefont','br','hr','input','img','link','meta');
$html = strip_tags($html, '<marker/><a><b><blockquote><body><br><br/><dd><del><div><dl><dt><em><font><form><h1><h2><h3><h4><h5><h6><hr><hr/><i><img><input><label><li><ol><option><p><pre><s><select><small><span><strike><strong><sub><sup><table><tablehead><tcpdf><td><textarea><th><thead><tr><tt><u><ul>');
$html = preg_replace('/<pre/', '<xre', $html);
$html = preg_replace('/<(table|tr|td|th|tcpdf|blockquote|dd|div|dl|dt|form|h1|h2|h3|h4|h5|h6|br|hr|li|ol|ul|p)([^\>]*)>[\n\r\t]+/', '<\\1\\2>', $html);
$html = preg_replace('@(\r\n|\r)@', "\n", $html);
$repTable = array("\t" => ' ', "\0" => ' ', "\x0B" => ' ', "\\" => "\\\\");
$html = strtr($html, $repTable);
$offset = 0;
while (($offset < strlen($html)) AND ($pos = strpos($html, '</pre>', $offset)) !== false) {
$html_a = substr($html, 0, $offset);
$html_b = substr($html, $offset, ($pos - $offset + 6));
while (preg_match("'<xre([^\>]*)>(.*?)\n(.*?)</pre>'si", $html_b)) {
$html_b = preg_replace("'<xre([^\>]*)>(.*?)\n(.*?)</pre>'si", "<xre\\1>\\2<br />\\3</pre>", $html_b);
}
while (preg_match("'<xre([^\>]*)>(.*?)".$this->re_space['p']."(.*?)</pre>'".$this->re_space['m'], $html_b)) {
$html_b = preg_replace("'<xre([^\>]*)>(.*?)".$this->re_space['p']."(.*?)</pre>'".$this->re_space['m'], "<xre\\1>\\2 \\3</pre>", $html_b);
}
$html = $html_a.$html_b.substr($html, $pos + 6);
$offset = strlen($html_a.$html_b);
}
$offset = 0;
while (($offset < strlen($html)) AND ($pos = strpos($html, '</textarea>', $offset)) !== false) {
$html_a = substr($html, 0, $offset);
$html_b = substr($html, $offset, ($pos - $offset + 11));
while (preg_match("'<textarea([^\>]*)>(.*?)\n(.*?)</textarea>'si", $html_b)) {
$html_b = preg_replace("'<textarea([^\>]*)>(.*?)\n(.*?)</textarea>'si", "<textarea\\1>\\2<TBR>\\3</textarea>", $html_b);
$html_b = preg_replace("'<textarea([^\>]*)>(.*?)[\"](.*?)</textarea>'si", "<textarea\\1>\\2''\\3</textarea>", $html_b);
}
$html = $html_a.$html_b.substr($html, $pos + 11);
$offset = strlen($html_a.$html_b);
}
$html = preg_replace('/([\s]*)<option/si', '<option', $html);
$html = preg_replace('/<\/option>([\s]*)/si', '</option>', $html);
$offset = 0;
while (($offset < strlen($html)) AND ($pos = strpos($html, '</option>', $offset)) !== false) {
$html_a = substr($html, 0, $offset);
$html_b = substr($html, $offset, ($pos - $offset + 9));
while (preg_match("'<option([^\>]*)>(.*?)</option>'si", $html_b)) {
$html_b = preg_replace("'<option([\s]+)value=\"([^\"]*)\"([^\>]*)>(.*?)</option>'si", "\\2#!TaB!#\\4#!NwL!#", $html_b);
$html_b = preg_replace("'<option([^\>]*)>(.*?)</option>'si", "\\2#!NwL!#", $html_b);
}
$html = $html_a.$html_b.substr($html, $pos + 9);
$offset = strlen($html_a.$html_b);
}
if (preg_match("'</select'si", $html)) {
$html = preg_replace("'<select([^\>]*)>'si", "<select\\1 opt=\"", $html);
$html = preg_replace("'#!NwL!#</select>'si", "\" />", $html);
}
$html = str_replace("\n", ' ', $html);
$html = str_replace('<TBR>', "\n", $html);
$html = preg_replace('/[\s]+<\/(table|tr|ul|ol|dl)>/', '</\\1>', $html);
$html = preg_replace('/'.$this->re_space['p'].'+<\/(td|th|li|dt|dd)>/'.$this->re_space['m'], '</\\1>', $html);
$html = preg_replace('/[\s]+<(tr|td|th|li|dt|dd)/', '<\\1', $html);
$html = preg_replace('/'.$this->re_space['p'].'+<(ul|ol|dl|br)/'.$this->re_space['m'], '<\\1', $html);
$html = preg_replace('/<\/(table|tr|td|th|blockquote|dd|dt|dl|div|dt|h1|h2|h3|h4|h5|h6|hr|li|ol|ul|p)>[\s]+</', '</\\1><', $html);
$html = preg_replace('/<\/(td|th)>/', '<marker style="font-size:0"/></\\1>', $html);
$html = preg_replace('/<\/table>([\s]*)<marker style="font-size:0"\/>/', '</table>', $html);
$html = preg_replace('/'.$this->re_space['p'].'+<img/'.$this->re_space['m'], chr(32).'<img', $html);
$html = preg_replace('/<img([^\>]*)>[\s]+([^\<])/xi', '<img\\1> \\2', $html);
$html = preg_replace('/<img([^\>]*)>/xi', '<img\\1><span><marker style="font-size:0"/></span>', $html);
$html = preg_replace('/<xre/', '<pre', $html);
$html = preg_replace('/<textarea([^\>]*)>([^\<]*)<\/textarea>/xi', '<textarea\\1 value="\\2" />', $html);
$html = preg_replace('/<li([^\>]*)><\/li>/', '<li\\1> </li>', $html);
$html = preg_replace('/<li([^\>]*)>'.$this->re_space['p'].'*<img/'.$this->re_space['m'], '<li\\1><font size="1"> </font><img', $html);
$html = preg_replace('/<([^\>\/]*)>[\s]/', '<\\1> ', $html);
$html = preg_replace('/[\s]<\/([^\>]*)>/', ' </\\1>', $html);
$html = preg_replace('/<su([bp])/', '<zws/><su\\1', $html);
$html = preg_replace('/<\/su([bp])>/', '</su\\1><zws/>', $html);
$html = preg_replace('/'.$this->re_space['p'].'+/'.$this->re_space['m'], chr(32), $html);
$html = $this->stringTrim($html);
$html = preg_replace('/<li><br([^\>]*)>/', '<li> <br\\1>', $html);
$html = preg_replace('/^<img/', '<span style="font-size:0"><br /></span> <img', $html, 1);
$tagpattern = '/(<[^>]+>)/';
$a = preg_split($tagpattern, $html, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY);
$maxel = count($a);
$elkey = 0;
$key = 0;
$dom = array();
$dom[$key] = array();
$dom[$key]['tag'] = false;
$dom[$key]['block'] = false;
$dom[$key]['value'] = '';
$dom[$key]['parent'] = 0;
$dom[$key]['hide'] = false;
$dom[$key]['fontname'] = $this->FontFamily;
$dom[$key]['fontstyle'] = $this->FontStyle;
$dom[$key]['fontsize'] = $this->FontSizePt;
$dom[$key]['font-stretch'] = $this->font_stretching;
$dom[$key]['letter-spacing'] = $this->font_spacing;
$dom[$key]['stroke'] = $this->textstrokewidth;
$dom[$key]['fill'] = (($this->textrendermode % 2) == 0);
$dom[$key]['clip'] = ($this->textrendermode > 3);
$dom[$key]['line-height'] = $this->cell_height_ratio;
$dom[$key]['bgcolor'] = false;
$dom[$key]['fgcolor'] = $this->fgcolor;
$dom[$key]['strokecolor'] = $this->strokecolor;
$dom[$key]['align'] = '';
$dom[$key]['listtype'] = '';
$dom[$key]['text-indent'] = 0;
$dom[$key]['text-transform'] = '';
$dom[$key]['border'] = array();
$dom[$key]['dir'] = $this->rtl?'rtl':'ltr';
$thead = false;
++$key;
$level = array();
array_push($level, 0);
while ($elkey < $maxel) {
$dom[$key] = array();
$element = $a[$elkey];
$dom[$key]['elkey'] = $elkey;
if (preg_match($tagpattern, $element)) {
$element = substr($element, 1, -1);
preg_match('/[\/]?([a-zA-Z0-9]*)/', $element, $tag);
$tagname = strtolower($tag[1]);
if ($tagname == 'thead') {
if ($element[0] == '/') {
$thead = false;
} else {
$thead = true;
}
++$elkey;
continue;
}
$dom[$key]['tag'] = true;
$dom[$key]['value'] = $tagname;
if (in_array($dom[$key]['value'], $blocktags)) {
$dom[$key]['block'] = true;
} else {
$dom[$key]['block'] = false;
}
if ($element[0] == '/') {
$dom[$key]['opening'] = false;
$dom[$key]['parent'] = end($level);
array_pop($level);
$dom[$key]['hide'] = $dom[($dom[($dom[$key]['parent'])]['parent'])]['hide'];
$dom[$key]['fontname'] = $dom[($dom[($dom[$key]['parent'])]['parent'])]['fontname'];
$dom[$key]['fontstyle'] = $dom[($dom[($dom[$key]['parent'])]['parent'])]['fontstyle'];
$dom[$key]['fontsize'] = $dom[($dom[($dom[$key]['parent'])]['parent'])]['fontsize'];
$dom[$key]['font-stretch'] = $dom[($dom[($dom[$key]['parent'])]['parent'])]['font-stretch'];
$dom[$key]['letter-spacing'] = $dom[($dom[($dom[$key]['parent'])]['parent'])]['letter-spacing'];
$dom[$key]['stroke'] = $dom[($dom[($dom[$key]['parent'])]['parent'])]['stroke'];
$dom[$key]['fill'] = $dom[($dom[($dom[$key]['parent'])]['parent'])]['fill'];
$dom[$key]['clip'] = $dom[($dom[($dom[$key]['parent'])]['parent'])]['clip'];
$dom[$key]['line-height'] = $dom[($dom[($dom[$key]['parent'])]['parent'])]['line-height'];
$dom[$key]['bgcolor'] = $dom[($dom[($dom[$key]['parent'])]['parent'])]['bgcolor'];
$dom[$key]['fgcolor'] = $dom[($dom[($dom[$key]['parent'])]['parent'])]['fgcolor'];
$dom[$key]['strokecolor'] = $dom[($dom[($dom[$key]['parent'])]['parent'])]['strokecolor'];
$dom[$key]['align'] = $dom[($dom[($dom[$key]['parent'])]['parent'])]['align'];
$dom[$key]['text-transform'] = $dom[($dom[($dom[$key]['parent'])]['parent'])]['text-transform'];
$dom[$key]['dir'] = $dom[($dom[($dom[$key]['parent'])]['parent'])]['dir'];
if (isset($dom[($dom[($dom[$key]['parent'])]['parent'])]['listtype'])) {
$dom[$key]['listtype'] = $dom[($dom[($dom[$key]['parent'])]['parent'])]['listtype'];
}
if (($dom[$key]['value'] == 'tr') AND (!isset($dom[($dom[($dom[$key]['parent'])]['parent'])]['cols']))) {
$dom[($dom[($dom[$key]['parent'])]['parent'])]['cols'] = $dom[($dom[$key]['parent'])]['cols'];
}
if (($dom[$key]['value'] == 'td') OR ($dom[$key]['value'] == 'th')) {
$dom[($dom[$key]['parent'])]['content'] = $csstagarray;
for ($i = ($dom[$key]['parent'] + 1); $i < $key; ++$i) {
$dom[($dom[$key]['parent'])]['content'] .= stripslashes($a[$dom[$i]['elkey']]);
}
$key = $i;
$dom[($dom[$key]['parent'])]['content'] = str_replace('<table', '<table nested="true"', $dom[($dom[$key]['parent'])]['content']);
$dom[($dom[$key]['parent'])]['content'] = str_replace('<thead>', '', $dom[($dom[$key]['parent'])]['content']);
$dom[($dom[$key]['parent'])]['content'] = str_replace('</thead>', '', $dom[($dom[$key]['parent'])]['content']);
}
if (($dom[$key]['value'] == 'tr') AND ($dom[($dom[$key]['parent'])]['thead'] === true)) {
if (TCPDF_STATIC::empty_string($dom[($dom[($dom[$key]['parent'])]['parent'])]['thead'])) {
$dom[($dom[($dom[$key]['parent'])]['parent'])]['thead'] = $csstagarray.$a[$dom[($dom[($dom[$key]['parent'])]['parent'])]['elkey']];
}
for ($i = $dom[$key]['parent']; $i <= $key; ++$i) {
$dom[($dom[($dom[$key]['parent'])]['parent'])]['thead'] .= $a[$dom[$i]['elkey']];
}
if (!isset($dom[($dom[$key]['parent'])]['attribute'])) {
$dom[($dom[$key]['parent'])]['attribute'] = array();
}
$dom[($dom[$key]['parent'])]['attribute']['nobr'] = 'true';
}
if (($dom[$key]['value'] == 'table') AND (!TCPDF_STATIC::empty_string($dom[($dom[$key]['parent'])]['thead']))) {
$dom[($dom[$key]['parent'])]['thead'] = str_replace(' nobr="true"', '', $dom[($dom[$key]['parent'])]['thead']);
$dom[($dom[$key]['parent'])]['thead'] .= '</tablehead>';
}
} else {
$dom[$key]['opening'] = true;
$dom[$key]['parent'] = end($level);
if ((substr($element, -1, 1) == '/') OR (in_array($dom[$key]['value'], $selfclosingtags))) {
$dom[$key]['self'] = true;
} else {
array_push($level, $key);
$dom[$key]['self'] = false;
}
$parentkey = 0;
if ($key > 0) {
$parentkey = $dom[$key]['parent'];
$dom[$key]['hide'] = $dom[$parentkey]['hide'];
$dom[$key]['fontname'] = $dom[$parentkey]['fontname'];
$dom[$key]['fontstyle'] = $dom[$parentkey]['fontstyle'];
$dom[$key]['fontsize'] = $dom[$parentkey]['fontsize'];
$dom[$key]['font-stretch'] = $dom[$parentkey]['font-stretch'];
$dom[$key]['letter-spacing'] = $dom[$parentkey]['letter-spacing'];
$dom[$key]['stroke'] = $dom[$parentkey]['stroke'];
$dom[$key]['fill'] = $dom[$parentkey]['fill'];
$dom[$key]['clip'] = $dom[$parentkey]['clip'];
$dom[$key]['line-height'] = $dom[$parentkey]['line-height'];
$dom[$key]['bgcolor'] = $dom[$parentkey]['bgcolor'];
$dom[$key]['fgcolor'] = $dom[$parentkey]['fgcolor'];
$dom[$key]['strokecolor'] = $dom[$parentkey]['strokecolor'];
$dom[$key]['align'] = $dom[$parentkey]['align'];
$dom[$key]['listtype'] = $dom[$parentkey]['listtype'];
$dom[$key]['text-indent'] = $dom[$parentkey]['text-indent'];
$dom[$key]['text-transform'] = $dom[$parentkey]['text-transform'];
$dom[$key]['border'] = array();
$dom[$key]['dir'] = $dom[$parentkey]['dir'];
}
preg_match_all('/([^=\s]*)[\s]*=[\s]*"([^"]*)"/', $element, $attr_array, PREG_PATTERN_ORDER);
$dom[$key]['attribute'] = array();
foreach($attr_array[1] as $id => $name) {
$dom[$key]['attribute'][strtolower($name)] = $attr_array[2][$id];
}
if (!empty($css)) {
list($dom[$key]['csssel'], $dom[$key]['cssdata']) = TCPDF_STATIC::getCSSdataArray($dom, $key, $css);
$dom[$key]['attribute']['style'] = TCPDF_STATIC::getTagStyleFromCSSarray($dom[$key]['cssdata']);
}
if (isset($dom[$key]['attribute']['style']) AND !empty($dom[$key]['attribute']['style'])) {
preg_match_all('/([^;:\s]*):([^;]*)/', $dom[$key]['attribute']['style'], $style_array, PREG_PATTERN_ORDER);
$dom[$key]['style'] = array();
foreach($style_array[1] as $id => $name) {
$dom[$key]['style'][strtolower($name)] = trim($style_array[2][$id]);
}
if (isset($dom[$key]['style']['direction'])) {
$dom[$key]['dir'] = $dom[$key]['style']['direction'];
}
if (isset($dom[$key]['style']['display'])) {
$dom[$key]['hide'] = (trim(strtolower($dom[$key]['style']['display'])) == 'none');
}
if (isset($dom[$key]['style']['font-family'])) {
$dom[$key]['fontname'] = $this->getFontFamilyName($dom[$key]['style']['font-family']);
}
if (isset($dom[$key]['style']['list-style-type'])) {
$dom[$key]['listtype'] = trim(strtolower($dom[$key]['style']['list-style-type']));
if ($dom[$key]['listtype'] == 'inherit') {
$dom[$key]['listtype'] = $dom[$parentkey]['listtype'];
}
}
if (isset($dom[$key]['style']['text-indent'])) {
$dom[$key]['text-indent'] = $this->getHTMLUnitToUnits($dom[$key]['style']['text-indent']);
if ($dom[$key]['text-indent'] == 'inherit') {
$dom[$key]['text-indent'] = $dom[$parentkey]['text-indent'];
}
}
if (isset($dom[$key]['style']['text-transform'])) {
$dom[$key]['text-transform'] = $dom[$key]['style']['text-transform'];
}
if (isset($dom[$key]['style']['font-size'])) {
$fsize = trim($dom[$key]['style']['font-size']);
$dom[$key]['fontsize'] = $this->getHTMLFontUnits($fsize, $dom[0]['fontsize'], $dom[$parentkey]['fontsize'], 'pt');
}
if (isset($dom[$key]['style']['font-stretch'])) {
$dom[$key]['font-stretch'] = $this->getCSSFontStretching($dom[$key]['style']['font-stretch'], $dom[$parentkey]['font-stretch']);
}
if (isset($dom[$key]['style']['letter-spacing'])) {
$dom[$key]['letter-spacing'] = $this->getCSSFontSpacing($dom[$key]['style']['letter-spacing'], $dom[$parentkey]['letter-spacing']);
}
if (isset($dom[$key]['style']['line-height'])) {
$lineheight = trim($dom[$key]['style']['line-height']);
switch ($lineheight) {
case 'normal': {
$dom[$key]['line-height'] = $dom[0]['line-height'];
break;
}
case 'inherit': {
$dom[$key]['line-height'] = $dom[$parentkey]['line-height'];
}
default: {
if (is_numeric($lineheight)) {
$lineheight = ($lineheight * 100).'%';
}
$dom[$key]['line-height'] = $this->getHTMLUnitToUnits($lineheight, 1, '%', true);
if (substr($lineheight, -1) !== '%') {
if ($dom[$key]['fontsize'] <= 0) {
$dom[$key]['line-height'] = 1;
} else {
$dom[$key]['line-height'] = (($dom[$key]['line-height'] - $this->cell_padding['T'] - $this->cell_padding['B']) / $dom[$key]['fontsize']);
}
}
}
}
}
if (isset($dom[$key]['style']['font-weight'])) {
if (strtolower($dom[$key]['style']['font-weight'][0]) == 'n') {
if (strpos($dom[$key]['fontstyle'], 'B') !== false) {
$dom[$key]['fontstyle'] = str_replace('B', '', $dom[$key]['fontstyle']);
}
} elseif (strtolower($dom[$key]['style']['font-weight'][0]) == 'b') {
$dom[$key]['fontstyle'] .= 'B';
}
}
if (isset($dom[$key]['style']['font-style']) AND (strtolower($dom[$key]['style']['font-style'][0]) == 'i')) {
$dom[$key]['fontstyle'] .= 'I';
}
if (isset($dom[$key]['style']['color']) AND (!TCPDF_STATIC::empty_string($dom[$key]['style']['color']))) {
$dom[$key]['fgcolor'] = TCPDF_COLORS::convertHTMLColorToDec($dom[$key]['style']['color'], $this->spot_colors);
} elseif ($dom[$key]['value'] == 'a') {
$dom[$key]['fgcolor'] = $this->htmlLinkColorArray;
}
if (isset($dom[$key]['style']['background-color']) AND (!TCPDF_STATIC::empty_string($dom[$key]['style']['background-color']))) {
$dom[$key]['bgcolor'] = TCPDF_COLORS::convertHTMLColorToDec($dom[$key]['style']['background-color'], $this->spot_colors);
}
if (isset($dom[$key]['style']['text-decoration'])) {
$decors = explode(' ', strtolower($dom[$key]['style']['text-decoration']));
foreach ($decors as $dec) {
$dec = trim($dec);
if (!TCPDF_STATIC::empty_string($dec)) {
if ($dec[0] == 'u') {
$dom[$key]['fontstyle'] .= 'U';
} elseif ($dec[0] == 'l') {
$dom[$key]['fontstyle'] .= 'D';
} elseif ($dec[0] == 'o') {
$dom[$key]['fontstyle'] .= 'O';
}
}
}
} elseif ($dom[$key]['value'] == 'a') {
$dom[$key]['fontstyle'] = $this->htmlLinkFontStyle;
}
if (isset($dom[$key]['style']['width'])) {
$dom[$key]['width'] = $dom[$key]['style']['width'];
}
if (isset($dom[$key]['style']['height'])) {
$dom[$key]['height'] = $dom[$key]['style']['height'];
}
if (isset($dom[$key]['style']['text-align'])) {
$dom[$key]['align'] = strtoupper($dom[$key]['style']['text-align'][0]);
}
if (isset($dom[$key]['style']['border'])) {
$borderstyle = $this->getCSSBorderStyle($dom[$key]['style']['border']);
if (!empty($borderstyle)) {
$dom[$key]['border']['LTRB'] = $borderstyle;
}
}
if (isset($dom[$key]['style']['border-color'])) {
$brd_colors = preg_split('/[\s]+/', trim($dom[$key]['style']['border-color']));
if (isset($brd_colors[3])) {
$dom[$key]['border']['L']['color'] = TCPDF_COLORS::convertHTMLColorToDec($brd_colors[3], $this->spot_colors);
}
if (isset($brd_colors[1])) {
$dom[$key]['border']['R']['color'] = TCPDF_COLORS::convertHTMLColorToDec($brd_colors[1], $this->spot_colors);
}
if (isset($brd_colors[0])) {
$dom[$key]['border']['T']['color'] = TCPDF_COLORS::convertHTMLColorToDec($brd_colors[0], $this->spot_colors);
}
if (isset($brd_colors[2])) {
$dom[$key]['border']['B']['color'] = TCPDF_COLORS::convertHTMLColorToDec($brd_colors[2], $this->spot_colors);
}
}
if (isset($dom[$key]['style']['border-width'])) {
$brd_widths = preg_split('/[\s]+/', trim($dom[$key]['style']['border-width']));
if (isset($brd_widths[3])) {
$dom[$key]['border']['L']['width'] = $this->getCSSBorderWidth($brd_widths[3]);
}
if (isset($brd_widths[1])) {
$dom[$key]['border']['R']['width'] = $this->getCSSBorderWidth($brd_widths[1]);
}
if (isset($brd_widths[0])) {
$dom[$key]['border']['T']['width'] = $this->getCSSBorderWidth($brd_widths[0]);
}
if (isset($brd_widths[2])) {
$dom[$key]['border']['B']['width'] = $this->getCSSBorderWidth($brd_widths[2]);
}
}
if (isset($dom[$key]['style']['border-style'])) {
$brd_styles = preg_split('/[\s]+/', trim($dom[$key]['style']['border-style']));
if (isset($brd_styles[3]) AND ($brd_styles[3]!='none')) {
$dom[$key]['border']['L']['cap'] = 'square';
$dom[$key]['border']['L']['join'] = 'miter';
$dom[$key]['border']['L']['dash'] = $this->getCSSBorderDashStyle($brd_styles[3]);
if ($dom[$key]['border']['L']['dash'] < 0) {
$dom[$key]['border']['L'] = array();
}
}
if (isset($brd_styles[1])) {
$dom[$key]['border']['R']['cap'] = 'square';
$dom[$key]['border']['R']['join'] = 'miter';
$dom[$key]['border']['R']['dash'] = $this->getCSSBorderDashStyle($brd_styles[1]);
if ($dom[$key]['border']['R']['dash'] < 0) {
$dom[$key]['border']['R'] = array();
}
}
if (isset($brd_styles[0])) {
$dom[$key]['border']['T']['cap'] = 'square';
$dom[$key]['border']['T']['join'] = 'miter';
$dom[$key]['border']['T']['dash'] = $this->getCSSBorderDashStyle($brd_styles[0]);
if ($dom[$key]['border']['T']['dash'] < 0) {
$dom[$key]['border']['T'] = array();
}
}
if (isset($brd_styles[2])) {
$dom[$key]['border']['B']['cap'] = 'square';
$dom[$key]['border']['B']['join'] = 'miter';
$dom[$key]['border']['B']['dash'] = $this->getCSSBorderDashStyle($brd_styles[2]);
if ($dom[$key]['border']['B']['dash'] < 0) {
$dom[$key]['border']['B'] = array();
}
}
}
$cellside = array('L' => 'left', 'R' => 'right', 'T' => 'top', 'B' => 'bottom');
foreach ($cellside as $bsk => $bsv) {
if (isset($dom[$key]['style']['border-'.$bsv])) {
$borderstyle = $this->getCSSBorderStyle($dom[$key]['style']['border-'.$bsv]);
if (!empty($borderstyle)) {
$dom[$key]['border'][$bsk] = $borderstyle;
}
}
if (isset($dom[$key]['style']['border-'.$bsv.'-color'])) {
$dom[$key]['border'][$bsk]['color'] = TCPDF_COLORS::convertHTMLColorToDec($dom[$key]['style']['border-'.$bsv.'-color'], $this->spot_colors);
}
if (isset($dom[$key]['style']['border-'.$bsv.'-width'])) {
$dom[$key]['border'][$bsk]['width'] = $this->getCSSBorderWidth($dom[$key]['style']['border-'.$bsv.'-width']);
}
if (isset($dom[$key]['style']['border-'.$bsv.'-style'])) {
$dom[$key]['border'][$bsk]['dash'] = $this->getCSSBorderDashStyle($dom[$key]['style']['border-'.$bsv.'-style']);
if ($dom[$key]['border'][$bsk]['dash'] < 0) {
$dom[$key]['border'][$bsk] = array();
}
}
}
if (isset($dom[$key]['style']['padding'])) {
$dom[$key]['padding'] = $this->getCSSPadding($dom[$key]['style']['padding']);
} else {
$dom[$key]['padding'] = $this->cell_padding;
}
foreach ($cellside as $psk => $psv) {
if (isset($dom[$key]['style']['padding-'.$psv])) {
$dom[$key]['padding'][$psk] = $this->getHTMLUnitToUnits($dom[$key]['style']['padding-'.$psv], 0, 'px', false);
}
}
if (isset($dom[$key]['style']['margin'])) {
$dom[$key]['margin'] = $this->getCSSMargin($dom[$key]['style']['margin']);
} else {
$dom[$key]['margin'] = $this->cell_margin;
}
foreach ($cellside as $psk => $psv) {
if (isset($dom[$key]['style']['margin-'.$psv])) {
$dom[$key]['margin'][$psk] = $this->getHTMLUnitToUnits(str_replace('auto', '0', $dom[$key]['style']['margin-'.$psv]), 0, 'px', false);
}
}
if (isset($dom[$key]['style']['border-spacing'])) {
$dom[$key]['border-spacing'] = $this->getCSSBorderMargin($dom[$key]['style']['border-spacing']);
}
if (isset($dom[$key]['style']['page-break-inside']) AND ($dom[$key]['style']['page-break-inside'] == 'avoid')) {
$dom[$key]['attribute']['nobr'] = 'true';
}
if (isset($dom[$key]['style']['page-break-before'])) {
if ($dom[$key]['style']['page-break-before'] == 'always') {
$dom[$key]['attribute']['pagebreak'] = 'true';
} elseif ($dom[$key]['style']['page-break-before'] == 'left') {
$dom[$key]['attribute']['pagebreak'] = 'left';
} elseif ($dom[$key]['style']['page-break-before'] == 'right') {
$dom[$key]['attribute']['pagebreak'] = 'right';
}
}
if (isset($dom[$key]['style']['page-break-after'])) {
if ($dom[$key]['style']['page-break-after'] == 'always') {
$dom[$key]['attribute']['pagebreakafter'] = 'true';
} elseif ($dom[$key]['style']['page-break-after'] == 'left') {
$dom[$key]['attribute']['pagebreakafter'] = 'left';
} elseif ($dom[$key]['style']['page-break-after'] == 'right') {
$dom[$key]['attribute']['pagebreakafter'] = 'right';
}
}
}
if (isset($dom[$key]['attribute']['display'])) {
$dom[$key]['hide'] = (trim(strtolower($dom[$key]['attribute']['display'])) == 'none');
}
if (isset($dom[$key]['attribute']['border']) AND ($dom[$key]['attribute']['border'] != 0)) {
$borderstyle = $this->getCSSBorderStyle($dom[$key]['attribute']['border'].' solid black');
if (!empty($borderstyle)) {
$dom[$key]['border']['LTRB'] = $borderstyle;
}
}
if ($dom[$key]['value'] == 'font') {
if (isset($dom[$key]['attribute']['face'])) {
$dom[$key]['fontname'] = $this->getFontFamilyName($dom[$key]['attribute']['face']);
}
if (isset($dom[$key]['attribute']['size'])) {
if ($key > 0) {
if ($dom[$key]['attribute']['size'][0] == '+') {
$dom[$key]['fontsize'] = $dom[($dom[$key]['parent'])]['fontsize'] + intval(substr($dom[$key]['attribute']['size'], 1));
} elseif ($dom[$key]['attribute']['size'][0] == '-') {
$dom[$key]['fontsize'] = $dom[($dom[$key]['parent'])]['fontsize'] - intval(substr($dom[$key]['attribute']['size'], 1));
} else {
$dom[$key]['fontsize'] = intval($dom[$key]['attribute']['size']);
}
} else {
$dom[$key]['fontsize'] = intval($dom[$key]['attribute']['size']);
}
}
}
if ((($dom[$key]['value'] == 'ul') OR ($dom[$key]['value'] == 'ol') OR ($dom[$key]['value'] == 'dl'))
AND (!isset($dom[$key]['align']) OR TCPDF_STATIC::empty_string($dom[$key]['align']) OR ($dom[$key]['align'] != 'J'))) {
if ($this->rtl) {
$dom[$key]['align'] = 'R';
} else {
$dom[$key]['align'] = 'L';
}
}
if (($dom[$key]['value'] == 'small') OR ($dom[$key]['value'] == 'sup') OR ($dom[$key]['value'] == 'sub')) {
if (!isset($dom[$key]['attribute']['size']) AND !isset($dom[$key]['style']['font-size'])) {
$dom[$key]['fontsize'] = $dom[$key]['fontsize'] * K_SMALL_RATIO;
}
}
if (($dom[$key]['value'] == 'strong') OR ($dom[$key]['value'] == 'b')) {
$dom[$key]['fontstyle'] .= 'B';
}
if (($dom[$key]['value'] == 'em') OR ($dom[$key]['value'] == 'i')) {
$dom[$key]['fontstyle'] .= 'I';
}
if ($dom[$key]['value'] == 'u') {
$dom[$key]['fontstyle'] .= 'U';
}
if (($dom[$key]['value'] == 'del') OR ($dom[$key]['value'] == 's') OR ($dom[$key]['value'] == 'strike')) {
$dom[$key]['fontstyle'] .= 'D';
}
if (!isset($dom[$key]['style']['text-decoration']) AND ($dom[$key]['value'] == 'a')) {
$dom[$key]['fontstyle'] = $this->htmlLinkFontStyle;
}
if (($dom[$key]['value'] == 'pre') OR ($dom[$key]['value'] == 'tt')) {
$dom[$key]['fontname'] = $this->default_monospaced_font;
}
if (!empty($dom[$key]['value']) AND ($dom[$key]['value'][0] == 'h') AND (intval($dom[$key]['value']{1}) > 0) AND (intval($dom[$key]['value']{1}) < 7)) {
if (!isset($dom[$key]['attribute']['size']) AND !isset($dom[$key]['style']['font-size'])) {
$headsize = (4 - intval($dom[$key]['value']{1})) * 2;
$dom[$key]['fontsize'] = $dom[0]['fontsize'] + $headsize;
}
if (!isset($dom[$key]['style']['font-weight'])) {
$dom[$key]['fontstyle'] .= 'B';
}
}
if (($dom[$key]['value'] == 'table')) {
$dom[$key]['rows'] = 0;
$dom[$key]['trids'] = array();
$dom[$key]['thead'] = '';
}
if (($dom[$key]['value'] == 'tr')) {
$dom[$key]['cols'] = 0;
if ($thead) {
$dom[$key]['thead'] = true;
} else {
$dom[$key]['thead'] = false;
++$dom[($dom[$key]['parent'])]['rows'];
array_push($dom[($dom[$key]['parent'])]['trids'], $key);
}
}
if (($dom[$key]['value'] == 'th') OR ($dom[$key]['value'] == 'td')) {
if (isset($dom[$key]['attribute']['colspan'])) {
$colspan = intval($dom[$key]['attribute']['colspan']);
} else {
$colspan = 1;
}
$dom[$key]['attribute']['colspan'] = $colspan;
$dom[($dom[$key]['parent'])]['cols'] += $colspan;
}
if (isset($dom[$key]['attribute']['dir'])) {
$dom[$key]['dir'] = $dom[$key]['attribute']['dir'];
}
if (isset($dom[$key]['attribute']['color']) AND (!TCPDF_STATIC::empty_string($dom[$key]['attribute']['color']))) {
$dom[$key]['fgcolor'] = TCPDF_COLORS::convertHTMLColorToDec($dom[$key]['attribute']['color'], $this->spot_colors);
} elseif (!isset($dom[$key]['style']['color']) AND ($dom[$key]['value'] == 'a')) {
$dom[$key]['fgcolor'] = $this->htmlLinkColorArray;
}
if (isset($dom[$key]['attribute']['bgcolor']) AND (!TCPDF_STATIC::empty_string($dom[$key]['attribute']['bgcolor']))) {
$dom[$key]['bgcolor'] = TCPDF_COLORS::convertHTMLColorToDec($dom[$key]['attribute']['bgcolor'], $this->spot_colors);
}
if (isset($dom[$key]['attribute']['strokecolor']) AND (!TCPDF_STATIC::empty_string($dom[$key]['attribute']['strokecolor']))) {
$dom[$key]['strokecolor'] = TCPDF_COLORS::convertHTMLColorToDec($dom[$key]['attribute']['strokecolor'], $this->spot_colors);
}
if (isset($dom[$key]['attribute']['width'])) {
$dom[$key]['width'] = $dom[$key]['attribute']['width'];
}
if (isset($dom[$key]['attribute']['height'])) {
$dom[$key]['height'] = $dom[$key]['attribute']['height'];
}
if (isset($dom[$key]['attribute']['align']) AND (!TCPDF_STATIC::empty_string($dom[$key]['attribute']['align'])) AND ($dom[$key]['value'] !== 'img')) {
$dom[$key]['align'] = strtoupper($dom[$key]['attribute']['align'][0]);
}
if (isset($dom[$key]['attribute']['stroke'])) {
$dom[$key]['stroke'] = $this->getHTMLUnitToUnits($dom[$key]['attribute']['stroke'], $dom[$key]['fontsize'], 'pt', true);
}
if (isset($dom[$key]['attribute']['fill'])) {
if ($dom[$key]['attribute']['fill'] == 'true') {
$dom[$key]['fill'] = true;
} else {
$dom[$key]['fill'] = false;
}
}
if (isset($dom[$key]['attribute']['clip'])) {
if ($dom[$key]['attribute']['clip'] == 'true') {
$dom[$key]['clip'] = true;
} else {
$dom[$key]['clip'] = false;
}
}
}
} else {
$dom[$key]['tag'] = false;
$dom[$key]['block'] = false;
$dom[$key]['parent'] = end($level);
$dom[$key]['dir'] = $dom[$dom[$key]['parent']]['dir'];
if (!empty($dom[$dom[$key]['parent']]['text-transform'])) {
if (function_exists('mb_convert_case')) {
$ttm = array('capitalize' => MB_CASE_TITLE, 'uppercase' => MB_CASE_UPPER, 'lowercase' => MB_CASE_LOWER);
if (isset($ttm[$dom[$dom[$key]['parent']]['text-transform']])) {
$element = mb_convert_case($element, $ttm[$dom[$dom[$key]['parent']]['text-transform']], $this->encoding);
}
} elseif (!$this->isunicode) {
switch ($dom[$dom[$key]['parent']]['text-transform']) {
case 'capitalize': {
$element = ucwords(strtolower($element));
break;
}
case 'uppercase': {
$element = strtoupper($element);
break;
}
case 'lowercase': {
$element = strtolower($element);
break;
}
}
}
}
$dom[$key]['value'] = stripslashes($this->unhtmlentities($element));
}
++$elkey;
++$key;
}
return $dom;
}
protected function getSpaceString() {
$spacestr = chr(32);
if ($this->isUnicodeFont()) {
$spacestr = chr(0).chr(32);
}
return $spacestr;
}
protected function getHashForTCPDFtagParams($data) {
return md5(strlen($data).$this->file_id.$data);
}
public function serializeTCPDFtagParameters($data) {
$encoded = urlencode(json_encode($data));
return $this->getHashForTCPDFtagParams($encoded).$encoded;
}
protected function unserializeTCPDFtagParameters($data) {
$hash = substr($data, 0, 32);
$encoded = substr($data, 32);
if ($hash != $this->getHashForTCPDFtagParams($encoded)) {
$this->Error('Invalid parameters');
}
return json_decode(urldecode($encoded), true);
}
public function writeHTMLCell($w, $h, $x, $y, $html='', $border=0, $ln=0, $fill=false, $reseth=true, $align='', $autopadding=true) {
return $this->MultiCell($w, $h, $html, $border, $align, $fill, $ln, $x, $y, $reseth, 0, true, $autopadding, 0, 'T', false);
}
public function writeHTML($html, $ln=true, $fill=false, $reseth=false, $cell=false, $align='') {
$gvars = $this->getGraphicVars();
$prev_cell_margin = $this->cell_margin;
$prev_cell_padding = $this->cell_padding;
$prevPage = $this->page;
$prevlMargin = $this->lMargin;
$prevrMargin = $this->rMargin;
$curfontname = $this->FontFamily;
$curfontstyle = $this->FontStyle;
$curfontsize = $this->FontSizePt;
$curfontascent = $this->getFontAscent($curfontname, $curfontstyle, $curfontsize);
$curfontdescent = $this->getFontDescent($curfontname, $curfontstyle, $curfontsize);
$curfontstretcing = $this->font_stretching;
$curfonttracking = $this->font_spacing;
$this->newline = true;
$newline = true;
$startlinepage = $this->page;
$minstartliney = $this->y;
$maxbottomliney = 0;
$startlinex = $this->x;
$startliney = $this->y;
$yshift = 0;
$loop = 0;
$curpos = 0;
$this_method_vars = array();
$undo = false;
$fontaligned = false;
$reverse_dir = false;
$this->premode = false;
if ($this->inxobj) {
$pask = count($this->xobjects[$this->xobjid]['annotations']);
} elseif (isset($this->PageAnnots[$this->page])) {
$pask = count($this->PageAnnots[$this->page]);
} else {
$pask = 0;
}
if ($this->inxobj) {
$startlinepos = strlen($this->xobjects[$this->xobjid]['outdata']);
} elseif (!$this->InFooter) {
if (isset($this->footerlen[$this->page])) {
$this->footerpos[$this->page] = $this->pagelen[$this->page] - $this->footerlen[$this->page];
} else {
$this->footerpos[$this->page] = $this->pagelen[$this->page];
}
$startlinepos = $this->footerpos[$this->page];
} else {
$startlinepos = $this->pagelen[$this->page];
}
$lalign = $align;
$plalign = $align;
if ($this->rtl) {
$w = $this->x - $this->lMargin;
} else {
$w = $this->w - $this->rMargin - $this->x;
}
$w -= ($this->cell_padding['L'] + $this->cell_padding['R']);
if ($cell) {
if ($this->rtl) {
$this->x -= $this->cell_padding['R'];
$this->lMargin += $this->cell_padding['L'];
} else {
$this->x += $this->cell_padding['L'];
$this->rMargin += $this->cell_padding['R'];
}
}
if ($this->customlistindent >= 0) {
$this->listindent = $this->customlistindent;
} else {
$this->listindent = $this->GetStringWidth('000000');
}
$this->listindentlevel = 0;
$prev_cell_height_ratio = $this->cell_height_ratio;
$prev_listnum = $this->listnum;
$prev_listordered = $this->listordered;
$prev_listcount = $this->listcount;
$prev_lispacer = $this->lispacer;
$this->listnum = 0;
$this->listordered = array();
$this->listcount = array();
$this->lispacer = '';
if ((TCPDF_STATIC::empty_string($this->lasth)) OR ($reseth)) {
$this->resetLastH();
}
$dom = $this->getHtmlDomArray($html);
$maxel = count($dom);
$key = 0;
while ($key < $maxel) {
if ($dom[$key]['tag'] AND $dom[$key]['opening'] AND $dom[$key]['hide']) {
$hidden_node_key = $key;
if ($dom[$key]['self']) {
++$key;
} else {
while (($key < $maxel) AND (!$dom[$key]['tag'] OR $dom[$key]['opening'] OR ($dom[$key]['parent'] != $hidden_node_key))) {
++$key;
}
++$key;
}
}
if ($dom[$key]['tag'] AND isset($dom[$key]['attribute']['pagebreak'])) {
if (($dom[$key]['attribute']['pagebreak'] == 'true') OR ($dom[$key]['attribute']['pagebreak'] == 'left') OR ($dom[$key]['attribute']['pagebreak'] == 'right')) {
$this->checkPageBreak($this->PageBreakTrigger + 1);
$this->htmlvspace = ($this->PageBreakTrigger + 1);
}
if ((($dom[$key]['attribute']['pagebreak'] == 'left') AND (((!$this->rtl) AND (($this->page % 2) == 0)) OR (($this->rtl) AND (($this->page % 2) != 0))))
OR (($dom[$key]['attribute']['pagebreak'] == 'right') AND (((!$this->rtl) AND (($this->page % 2) != 0)) OR (($this->rtl) AND (($this->page % 2) == 0))))) {
$this->checkPageBreak($this->PageBreakTrigger + 1);
$this->htmlvspace = ($this->PageBreakTrigger + 1);
}
}
if ($dom[$key]['tag'] AND $dom[$key]['opening'] AND isset($dom[$key]['attribute']['nobr']) AND ($dom[$key]['attribute']['nobr'] == 'true')) {
if (isset($dom[($dom[$key]['parent'])]['attribute']['nobr']) AND ($dom[($dom[$key]['parent'])]['attribute']['nobr'] == 'true')) {
$dom[$key]['attribute']['nobr'] = false;
} else {
$this->startTransaction();
$this_method_vars['html'] = $html;
$this_method_vars['ln'] = $ln;
$this_method_vars['fill'] = $fill;
$this_method_vars['reseth'] = $reseth;
$this_method_vars['cell'] = $cell;
$this_method_vars['align'] = $align;
$this_method_vars['gvars'] = $gvars;
$this_method_vars['prevPage'] = $prevPage;
$this_method_vars['prev_cell_margin'] = $prev_cell_margin;
$this_method_vars['prev_cell_padding'] = $prev_cell_padding;
$this_method_vars['prevlMargin'] = $prevlMargin;
$this_method_vars['prevrMargin'] = $prevrMargin;
$this_method_vars['curfontname'] = $curfontname;
$this_method_vars['curfontstyle'] = $curfontstyle;
$this_method_vars['curfontsize'] = $curfontsize;
$this_method_vars['curfontascent'] = $curfontascent;
$this_method_vars['curfontdescent'] = $curfontdescent;
$this_method_vars['curfontstretcing'] = $curfontstretcing;
$this_method_vars['curfonttracking'] = $curfonttracking;
$this_method_vars['minstartliney'] = $minstartliney;
$this_method_vars['maxbottomliney'] = $maxbottomliney;
$this_method_vars['yshift'] = $yshift;
$this_method_vars['startlinepage'] = $startlinepage;
$this_method_vars['startlinepos'] = $startlinepos;
$this_method_vars['startlinex'] = $startlinex;
$this_method_vars['startliney'] = $startliney;
$this_method_vars['newline'] = $newline;
$this_method_vars['loop'] = $loop;
$this_method_vars['curpos'] = $curpos;
$this_method_vars['pask'] = $pask;
$this_method_vars['lalign'] = $lalign;
$this_method_vars['plalign'] = $plalign;
$this_method_vars['w'] = $w;
$this_method_vars['prev_cell_height_ratio'] = $prev_cell_height_ratio;
$this_method_vars['prev_listnum'] = $prev_listnum;
$this_method_vars['prev_listordered'] = $prev_listordered;
$this_method_vars['prev_listcount'] = $prev_listcount;
$this_method_vars['prev_lispacer'] = $prev_lispacer;
$this_method_vars['fontaligned'] = $fontaligned;
$this_method_vars['key'] = $key;
$this_method_vars['dom'] = $dom;
}
}
if (($dom[$key]['value'] == 'tr') AND isset($dom[$key]['thead']) AND $dom[$key]['thead']) {
if (isset($dom[$key]['parent']) AND isset($dom[$dom[$key]['parent']]['thead']) AND !TCPDF_STATIC::empty_string($dom[$dom[$key]['parent']]['thead'])) {
$this->inthead = true;
$this->writeHTML($this->thead, false, false, false, false, '');
if (($this->y < $this->start_transaction_y) OR ($this->checkPageBreak($this->lasth, '', false))) {
$this->rollbackTransaction(true);
foreach ($this_method_vars as $vkey => $vval) {
$$vkey = $vval;
}
$tmp_thead = $this->thead;
$this->thead = '';
$pre_y = $this->y;
if ((!$this->checkPageBreak($this->PageBreakTrigger + 1)) AND ($this->y < $pre_y)) {
$startliney = $this->y;
}
$this->start_transaction_page = $this->page;
$this->start_transaction_y = $this->y;
$this->thead = $tmp_thead;
if (isset($dom[$dom[$key]['parent']]['attribute']['cellspacing'])) {
$tmp_cellspacing = $this->getHTMLUnitToUnits($dom[$dom[$key]['parent']]['attribute']['cellspacing'], 1, 'px');
} elseif (isset($dom[$dom[$key]['parent']]['border-spacing'])) {
$tmp_cellspacing = $dom[$dom[$key]['parent']]['border-spacing']['V'];
} else {
$tmp_cellspacing = 0;
}
$dom[$dom[$key]['parent']]['borderposition']['page'] = $this->page;
$dom[$dom[$key]['parent']]['borderposition']['column'] = $this->current_column;
$dom[$dom[$key]['parent']]['borderposition']['y'] = $this->y + $tmp_cellspacing;
$xoffset = ($this->x - $dom[$dom[$key]['parent']]['borderposition']['x']);
$dom[$dom[$key]['parent']]['borderposition']['x'] += $xoffset;
$dom[$dom[$key]['parent']]['borderposition']['xmax'] += $xoffset;
$this->writeHTML($this->thead, false, false, false, false, '');
}
}
while ( ($key < $maxel) AND (!(
($dom[$key]['tag'] AND $dom[$key]['opening'] AND ($dom[$key]['value'] == 'tr') AND (!isset($dom[$key]['thead']) OR !$dom[$key]['thead']))
OR ($dom[$key]['tag'] AND (!$dom[$key]['opening']) AND ($dom[$key]['value'] == 'table'))) )) {
++$key;
}
}
if ($dom[$key]['tag'] OR ($key == 0)) {
if ((($dom[$key]['value'] == 'table') OR ($dom[$key]['value'] == 'tr')) AND (isset($dom[$key]['align']))) {
$dom[$key]['align'] = ($this->rtl) ? 'R' : 'L';
}
if ((!$this->newline) AND ($dom[$key]['value'] == 'img') AND (isset($dom[$key]['height'])) AND ($dom[$key]['height'] > 0)) {
$imgh = $this->getHTMLUnitToUnits($dom[$key]['height'], ($dom[$key]['fontsize'] / $this->k), 'px');
$autolinebreak = false;
if (!empty($dom[$key]['width'])) {
$imgw = $this->getHTMLUnitToUnits($dom[$key]['width'], ($dom[$key]['fontsize'] / $this->k), 'px', false);
if (($imgw <= ($this->w - $this->lMargin - $this->rMargin - $this->cell_padding['L'] - $this->cell_padding['R']))
AND ((($this->rtl) AND (($this->x - $imgw) < ($this->lMargin + $this->cell_padding['L'])))
OR ((!$this->rtl) AND (($this->x + $imgw) > ($this->w - $this->rMargin - $this->cell_padding['R']))))) {
$autolinebreak = true;
$this->Ln('', $cell);
if ((!$dom[($key-1)]['tag']) AND ($dom[($key-1)]['value'] == ' ')) {
--$key;
}
}
}
if (!$autolinebreak) {
if ($this->inPageBody()) {
$pre_y = $this->y;
if ((!$this->checkPageBreak($imgh)) AND ($this->y < $pre_y)) {
$startliney = $this->y;
}
}
if ($this->page > $startlinepage) {
if (isset($this->footerlen[$startlinepage])) {
$curpos = $this->pagelen[$startlinepage] - $this->footerlen[$startlinepage];
}
$pagebuff = $this->getPageBuffer($startlinepage);
$linebeg = substr($pagebuff, $startlinepos, ($curpos - $startlinepos));
$tstart = substr($pagebuff, 0, $startlinepos);
$tend = substr($this->getPageBuffer($startlinepage), $curpos);
$this->setPageBuffer($startlinepage, $tstart.''.$tend);
$pagebuff = $this->getPageBuffer($this->page);
$tstart = substr($pagebuff, 0, $this->cntmrk[$this->page]);
$tend = substr($pagebuff, $this->cntmrk[$this->page]);
$yshift = ($minstartliney - $this->y);
if ($fontaligned) {
$yshift += ($curfontsize / $this->k);
}
$try = sprintf('1 0 0 1 0 %F cm', ($yshift * $this->k));
$this->setPageBuffer($this->page, $tstart."\nq\n".$try."\n".$linebeg."\nQ\n".$tend);
if (isset($this->PageAnnots[$this->page])) {
$next_pask = count($this->PageAnnots[$this->page]);
} else {
$next_pask = 0;
}
if (isset($this->PageAnnots[$startlinepage])) {
foreach ($this->PageAnnots[$startlinepage] as $pak => $pac) {
if ($pak >= $pask) {
$this->PageAnnots[$this->page][] = $pac;
unset($this->PageAnnots[$startlinepage][$pak]);
$npak = count($this->PageAnnots[$this->page]) - 1;
$this->PageAnnots[$this->page][$npak]['y'] -= $yshift;
}
}
}
$pask = $next_pask;
$startlinepos = $this->cntmrk[$this->page];
$startlinepage = $this->page;
$startliney = $this->y;
$this->newline = false;
}
$this->y += ($this->getCellHeight($curfontsize / $this->k) - ($curfontdescent * $this->cell_height_ratio) - $imgh);
$minstartliney = min($this->y, $minstartliney);
$maxbottomliney = ($startliney + $this->getCellHeight($curfontsize / $this->k));
}
} elseif (isset($dom[$key]['fontname']) OR isset($dom[$key]['fontstyle']) OR isset($dom[$key]['fontsize']) OR isset($dom[$key]['line-height'])) {
$pfontname = $curfontname;
$pfontstyle = $curfontstyle;
$pfontsize = $curfontsize;
$fontname = (isset($dom[$key]['fontname']) ? $dom[$key]['fontname'] : $curfontname);
$fontstyle = (isset($dom[$key]['fontstyle']) ? $dom[$key]['fontstyle'] : $curfontstyle);
$fontsize = (isset($dom[$key]['fontsize']) ? $dom[$key]['fontsize'] : $curfontsize);
$fontascent = $this->getFontAscent($fontname, $fontstyle, $fontsize);
$fontdescent = $this->getFontDescent($fontname, $fontstyle, $fontsize);
if (($fontname != $curfontname) OR ($fontstyle != $curfontstyle) OR ($fontsize != $curfontsize)
OR ($this->cell_height_ratio != $dom[$key]['line-height'])
OR ($dom[$key]['tag'] AND $dom[$key]['opening'] AND ($dom[$key]['value'] == 'li')) ) {
if (($key < ($maxel - 1)) AND (
($dom[$key]['tag'] AND $dom[$key]['opening'] AND ($dom[$key]['value'] == 'li'))
OR ($this->cell_height_ratio != $dom[$key]['line-height'])
OR (!$this->newline AND is_numeric($fontsize) AND is_numeric($curfontsize)
AND ($fontsize >= 0) AND ($curfontsize >= 0)
AND (($fontsize != $curfontsize) OR ($fontstyle != $curfontstyle) OR ($fontname != $curfontname)))
)) {
if ($this->page > $startlinepage) {
if (isset($this->footerlen[$startlinepage])) {
$curpos = $this->pagelen[$startlinepage] - $this->footerlen[$startlinepage];
}
$pagebuff = $this->getPageBuffer($startlinepage);
$linebeg = substr($pagebuff, $startlinepos, ($curpos - $startlinepos));
$tstart = substr($pagebuff, 0, $startlinepos);
$tend = substr($this->getPageBuffer($startlinepage), $curpos);
$this->setPageBuffer($startlinepage, $tstart.''.$tend);
$pagebuff = $this->getPageBuffer($this->page);
$tstart = substr($pagebuff, 0, $this->cntmrk[$this->page]);
$tend = substr($pagebuff, $this->cntmrk[$this->page]);
$yshift = ($minstartliney - $this->y);
$try = sprintf('1 0 0 1 0 %F cm', ($yshift * $this->k));
$this->setPageBuffer($this->page, $tstart."\nq\n".$try."\n".$linebeg."\nQ\n".$tend);
if (isset($this->PageAnnots[$this->page])) {
$next_pask = count($this->PageAnnots[$this->page]);
} else {
$next_pask = 0;
}
if (isset($this->PageAnnots[$startlinepage])) {
foreach ($this->PageAnnots[$startlinepage] as $pak => $pac) {
if ($pak >= $pask) {
$this->PageAnnots[$this->page][] = $pac;
unset($this->PageAnnots[$startlinepage][$pak]);
$npak = count($this->PageAnnots[$this->page]) - 1;
$this->PageAnnots[$this->page][$npak]['y'] -= $yshift;
}
}
}
$pask = $next_pask;
$startlinepos = $this->cntmrk[$this->page];
$startlinepage = $this->page;
$startliney = $this->y;
}
if (!isset($dom[$key]['line-height'])) {
$dom[$key]['line-height'] = $this->cell_height_ratio;
}
if (!$dom[$key]['block']) {
if (!(isset($dom[($key + 1)]) AND $dom[($key + 1)]['tag'] AND (!$dom[($key + 1)]['opening']) AND ($dom[($key + 1)]['value'] != 'li') AND $dom[$key]['tag'] AND (!$dom[$key]['opening']))) {
$this->y += (((($curfontsize * $this->cell_height_ratio) - ($fontsize * $dom[$key]['line-height'])) / $this->k) + $curfontascent - $fontascent - $curfontdescent + $fontdescent) / 2;
}
if (($dom[$key]['value'] != 'sup') AND ($dom[$key]['value'] != 'sub')) {
$current_line_align_data = array($key, $minstartliney, $maxbottomliney);
if (isset($line_align_data) AND (($line_align_data[0] == ($key - 1)) OR (($line_align_data[0] == ($key - 2)) AND (isset($dom[($key - 1)])) AND (preg_match('/^([\s]+)$/', $dom[($key - 1)]['value']) > 0)))) {
$minstartliney = min($this->y, $line_align_data[1]);
$maxbottomliney = max(($this->y + $this->getCellHeight($fontsize / $this->k)), $line_align_data[2]);
} else {
$minstartliney = min($this->y, $minstartliney);
$maxbottomliney = max(($this->y + $this->getCellHeight($fontsize / $this->k)), $maxbottomliney);
}
$line_align_data = $current_line_align_data;
}
}
$this->cell_height_ratio = $dom[$key]['line-height'];
$fontaligned = true;
}
$this->SetFont($fontname, $fontstyle, $fontsize);
$this->resetLastH();
$curfontname = $fontname;
$curfontstyle = $fontstyle;
$curfontsize = $fontsize;
$curfontascent = $fontascent;
$curfontdescent = $fontdescent;
}
}
$textstroke = isset($dom[$key]['stroke']) ? $dom[$key]['stroke'] : $this->textstrokewidth;
$textfill = isset($dom[$key]['fill']) ? $dom[$key]['fill'] : (($this->textrendermode % 2) == 0);
$textclip = isset($dom[$key]['clip']) ? $dom[$key]['clip'] : ($this->textrendermode > 3);
$this->setTextRenderingMode($textstroke, $textfill, $textclip);
if (isset($dom[$key]['font-stretch']) AND ($dom[$key]['font-stretch'] !== false)) {
$this->setFontStretching($dom[$key]['font-stretch']);
}
if (isset($dom[$key]['letter-spacing']) AND ($dom[$key]['letter-spacing'] !== false)) {
$this->setFontSpacing($dom[$key]['letter-spacing']);
}
if (($plalign == 'J') AND $dom[$key]['block']) {
$plalign = '';
}
$curpos = $this->pagelen[$startlinepage];
if (isset($dom[$key]['bgcolor']) AND ($dom[$key]['bgcolor'] !== false)) {
$this->SetFillColorArray($dom[$key]['bgcolor']);
$wfill = true;
} else {
$wfill = $fill | false;
}
if (isset($dom[$key]['fgcolor']) AND ($dom[$key]['fgcolor'] !== false)) {
$this->SetTextColorArray($dom[$key]['fgcolor']);
}
if (isset($dom[$key]['strokecolor']) AND ($dom[$key]['strokecolor'] !== false)) {
$this->SetDrawColorArray($dom[$key]['strokecolor']);
}
if (isset($dom[$key]['align'])) {
$lalign = $dom[$key]['align'];
}
if (TCPDF_STATIC::empty_string($lalign)) {
$lalign = $align;
}
}
if ($this->newline AND (strlen($dom[$key]['value']) > 0) AND ($dom[$key]['value'] != 'td') AND ($dom[$key]['value'] != 'th')) {
$newline = true;
$fontaligned = false;
if (isset($startlinex)) {
$yshift = ($minstartliney - $startliney);
if (($yshift > 0) OR ($this->page > $startlinepage)) {
$yshift = 0;
}
$t_x = 0;
$linew = abs($this->endlinex - $startlinex);
if ($this->inxobj) {
$pstart = substr($this->xobjects[$this->xobjid]['outdata'], 0, $startlinepos);
if (isset($opentagpos)) {
$midpos = $opentagpos;
} else {
$midpos = 0;
}
if ($midpos > 0) {
$pmid = substr($this->xobjects[$this->xobjid]['outdata'], $startlinepos, ($midpos - $startlinepos));
$pend = substr($this->xobjects[$this->xobjid]['outdata'], $midpos);
} else {
$pmid = substr($this->xobjects[$this->xobjid]['outdata'], $startlinepos);
$pend = '';
}
} else {
$pstart = substr($this->getPageBuffer($startlinepage), 0, $startlinepos);
if (isset($opentagpos) AND isset($this->footerlen[$startlinepage]) AND (!$this->InFooter)) {
$this->footerpos[$startlinepage] = $this->pagelen[$startlinepage] - $this->footerlen[$startlinepage];
$midpos = min($opentagpos, $this->footerpos[$startlinepage]);
} elseif (isset($opentagpos)) {
$midpos = $opentagpos;
} elseif (isset($this->footerlen[$startlinepage]) AND (!$this->InFooter)) {
$this->footerpos[$startlinepage] = $this->pagelen[$startlinepage] - $this->footerlen[$startlinepage];
$midpos = $this->footerpos[$startlinepage];
} else {
$midpos = 0;
}
if ($midpos > 0) {
$pmid = substr($this->getPageBuffer($startlinepage), $startlinepos, ($midpos - $startlinepos));
$pend = substr($this->getPageBuffer($startlinepage), $midpos);
} else {
$pmid = substr($this->getPageBuffer($startlinepage), $startlinepos);
$pend = '';
}
}
if ((isset($plalign) AND ((($plalign == 'C') OR ($plalign == 'J') OR (($plalign == 'R') AND (!$this->rtl)) OR (($plalign == 'L') AND ($this->rtl)))))) {
$tw = $w;
if (($plalign == 'J') AND $this->isRTLTextDir() AND ($this->num_columns > 1)) {
$tw += $this->cell_padding['R'];
}
if ($this->lMargin != $prevlMargin) {
$tw += ($prevlMargin - $this->lMargin);
}
if ($this->rMargin != $prevrMargin) {
$tw += ($prevrMargin - $this->rMargin);
}
$one_space_width = $this->GetStringWidth(chr(32));
$no = 0;
if ($this->isRTLTextDir()) {
$pos1 = TCPDF_STATIC::revstrpos($pmid, '[(');
if ($pos1 > 0) {
$pos1 = intval($pos1);
if ($this->isUnicodeFont()) {
$pos2 = intval(TCPDF_STATIC::revstrpos($pmid, '[('.chr(0).chr(32)));
$spacelen = 2;
} else {
$pos2 = intval(TCPDF_STATIC::revstrpos($pmid, '[('.chr(32)));
$spacelen = 1;
}
if ($pos1 == $pos2) {
$pmid = substr($pmid, 0, ($pos1 + 2)).substr($pmid, ($pos1 + 2 + $spacelen));
if (substr($pmid, $pos1, 4) == '[()]') {
$linew -= $one_space_width;
} elseif ($pos1 == strpos($pmid, '[(')) {
$no = 1;
}
}
}
} else {
$pos1 = TCPDF_STATIC::revstrpos($pmid, ')]');
if ($pos1 > 0) {
$pos1 = intval($pos1);
if ($this->isUnicodeFont()) {
$pos2 = intval(TCPDF_STATIC::revstrpos($pmid, chr(0).chr(32).')]')) + 2;
$spacelen = 2;
} else {
$pos2 = intval(TCPDF_STATIC::revstrpos($pmid, chr(32).')]')) + 1;
$spacelen = 1;
}
if ($pos1 == $pos2) {
$pmid = substr($pmid, 0, ($pos1 - $spacelen)).substr($pmid, $pos1);
$linew -= $one_space_width;
}
}
}
$mdiff = ($tw - $linew);
if ($plalign == 'C') {
if ($this->rtl) {
$t_x = -($mdiff / 2);
} else {
$t_x = ($mdiff / 2);
}
} elseif ($plalign == 'R') {
$t_x = $mdiff;
} elseif ($plalign == 'L') {
$t_x = -$mdiff;
} elseif (($plalign == 'J') AND ($plalign == $lalign)) {
if ($this->isRTLTextDir()) {
$t_x = -$mdiff;
}
$ns = 0;
$pmidtemp = $pmid;
$pmidtemp = preg_replace('/[\\\][\(]/x', '\\#!#OP#!#', $pmidtemp);
$pmidtemp = preg_replace('/[\\\][\)]/x', '\\#!#CP#!#', $pmidtemp);
if (preg_match_all('/\[\(([^\)]*)\)\]/x', $pmidtemp, $lnstring, PREG_PATTERN_ORDER)) {
$spacestr = $this->getSpaceString();
$maxkk = count($lnstring[1]) - 1;
for ($kk=0; $kk <= $maxkk; ++$kk) {
$lnstring[1][$kk] = str_replace('#!#OP#!#', '(', $lnstring[1][$kk]);
$lnstring[1][$kk] = str_replace('#!#CP#!#', ')', $lnstring[1][$kk]);
$lnstring[2][$kk] = substr_count($lnstring[1][$kk], $spacestr);
$ns += $lnstring[2][$kk];
$lnstring[3][$kk] = $ns;
}
if ($ns == 0) {
$ns = 1;
}
$spacewidth = ($mdiff / ($ns - $no)) * $this->k;
if ($this->FontSize <= 0) {
$this->FontSize = 1;
}
$spacewidthu = -1000 * ($mdiff + (($ns + $no) * $one_space_width)) / $ns / $this->FontSize;
if ($this->font_spacing != 0) {
$osw = -1000 * $this->font_spacing / $this->FontSize;
$spacewidthu += $osw;
}
$nsmax = $ns;
$ns = 0;
reset($lnstring);
$offset = 0;
$strcount = 0;
$prev_epsposbeg = 0;
$textpos = 0;
if ($this->isRTLTextDir()) {
$textpos = $this->wPt;
}
while (preg_match('/([0-9\.\+\-]*)[\s](Td|cm|m|l|c|re)[\s]/x', $pmid, $strpiece, PREG_OFFSET_CAPTURE, $offset) == 1) {
$stroffset = strpos($pmid, '[(', $offset);
if (($stroffset !== false) AND ($stroffset <= $strpiece[2][1])) {
$offset = strpos($pmid, ')]', $stroffset);
while (($offset !== false) AND ($pmid[($offset - 1)] == '\\')) {
$offset = strpos($pmid, ')]', ($offset + 1));
}
if ($offset === false) {
$this->Error('HTML Justification: malformed PDF code.');
}
continue;
}
if ($this->isRTLTextDir()) {
$spacew = ($spacewidth * ($nsmax - $ns));
} else {
$spacew = ($spacewidth * $ns);
}
$offset = $strpiece[2][1] + strlen($strpiece[2][0]);
$epsposend = strpos($pmid, $this->epsmarker.'Q', $offset);
if ($epsposend !== null) {
$epsposend += strlen($this->epsmarker.'Q');
$epsposbeg = strpos($pmid, 'q'.$this->epsmarker, $offset);
if ($epsposbeg === null) {
$epsposbeg = strpos($pmid, 'q'.$this->epsmarker, ($prev_epsposbeg - 6));
$prev_epsposbeg = $epsposbeg;
}
if (($epsposbeg > 0) AND ($epsposend > 0) AND ($offset > $epsposbeg) AND ($offset < $epsposend)) {
$trx = sprintf('1 0 0 1 %F 0 cm', $spacew);
$pmid_b = substr($pmid, 0, $epsposbeg);
$pmid_m = substr($pmid, $epsposbeg, ($epsposend - $epsposbeg));
$pmid_e = substr($pmid, $epsposend);
$pmid = $pmid_b."\nq\n".$trx."\n".$pmid_m."\nQ\n".$pmid_e;
$offset = $epsposend;
continue;
}
}
$currentxpos = 0;
switch ($strpiece[2][0]) {
case 'Td':
case 'cm':
case 'm':
case 'l': {
preg_match('/([0-9\.\+\-]*)[\s]('.$strpiece[1][0].')[\s]('.$strpiece[2][0].')([\s]*)/x', $pmid, $xmatches);
if (!isset($xmatches[1])) {
break;
}
$currentxpos = $xmatches[1];
$textpos = $currentxpos;
if (($strcount <= $maxkk) AND ($strpiece[2][0] == 'Td')) {
$ns = $lnstring[3][$strcount];
if ($this->isRTLTextDir()) {
$spacew = ($spacewidth * ($nsmax - $ns));
}
++$strcount;
}
if (preg_match('/([0-9\.\+\-]*)[\s]('.$strpiece[1][0].')[\s]('.$strpiece[2][0].')([\s]*)/x', $pmid, $pmatch) == 1) {
$newpmid = sprintf('%F',(floatval($pmatch[1]) + $spacew)).' '.$pmatch[2].' x*#!#*x'.$pmatch[3].$pmatch[4];
$pmid = str_replace($pmatch[0], $newpmid, $pmid);
unset($pmatch, $newpmid);
}
break;
}
case 're': {
if (!TCPDF_STATIC::empty_string($this->lispacer)) {
$this->lispacer = '';
continue;
}
preg_match('/([0-9\.\+\-]*)[\s]([0-9\.\+\-]*)[\s]([0-9\.\+\-]*)[\s]('.$strpiece[1][0].')[\s](re)([\s]*)/x', $pmid, $xmatches);
if (!isset($xmatches[1])) {
break;
}
$currentxpos = $xmatches[1];
$x_diff = 0;
$w_diff = 0;
if ($this->isRTLTextDir()) {
if ($currentxpos < $textpos) {
$x_diff = ($spacewidth * ($nsmax - $lnstring[3][$strcount]));
$w_diff = ($spacewidth * $lnstring[2][$strcount]);
} else {
if ($strcount > 0) {
$x_diff = ($spacewidth * ($nsmax - $lnstring[3][($strcount - 1)]));
$w_diff = ($spacewidth * $lnstring[2][($strcount - 1)]);
}
}
} else {
if ($currentxpos > $textpos) {
if ($strcount > 0) {
$x_diff = ($spacewidth * $lnstring[3][($strcount - 1)]);
}
$w_diff = ($spacewidth * $lnstring[2][$strcount]);
} else {
if ($strcount > 1) {
$x_diff = ($spacewidth * $lnstring[3][($strcount - 2)]);
}
if ($strcount > 0) {
$w_diff = ($spacewidth * $lnstring[2][($strcount - 1)]);
}
}
}
if (preg_match('/('.$xmatches[1].')[\s]('.$xmatches[2].')[\s]('.$xmatches[3].')[\s]('.$strpiece[1][0].')[\s](re)([\s]*)/x', $pmid, $pmatch) == 1) {
$newx = sprintf('%F',(floatval($pmatch[1]) + $x_diff));
$neww = sprintf('%F',(floatval($pmatch[3]) + $w_diff));
$newpmid = $newx.' '.$pmatch[2].' '.$neww.' '.$pmatch[4].' x*#!#*x'.$pmatch[5].$pmatch[6];
$pmid = str_replace($pmatch[0], $newpmid, $pmid);
unset($pmatch, $newpmid, $newx, $neww);
}
break;
}
case 'c': {
preg_match('/([0-9\.\+\-]*)[\s]([0-9\.\+\-]*)[\s]([0-9\.\+\-]*)[\s]([0-9\.\+\-]*)[\s]([0-9\.\+\-]*)[\s]('.$strpiece[1][0].')[\s](c)([\s]*)/x', $pmid, $xmatches);
if (!isset($xmatches[1])) {
break;
}
$currentxpos = $xmatches[1];
if (preg_match('/('.$xmatches[1].')[\s]('.$xmatches[2].')[\s]('.$xmatches[3].')[\s]('.$xmatches[4].')[\s]('.$xmatches[5].')[\s]('.$strpiece[1][0].')[\s](c)([\s]*)/x', $pmid, $pmatch) == 1) {
$newx1 = sprintf('%F',(floatval($pmatch[1]) + $spacew));
$newx2 = sprintf('%F',(floatval($pmatch[3]) + $spacew));
$newx3 = sprintf('%F',(floatval($pmatch[5]) + $spacew));
$newpmid = $newx1.' '.$pmatch[2].' '.$newx2.' '.$pmatch[4].' '.$newx3.' '.$pmatch[6].' x*#!#*x'.$pmatch[7].$pmatch[8];
$pmid = str_replace($pmatch[0], $newpmid, $pmid);
unset($pmatch, $newpmid, $newx1, $newx2, $newx3);
}
break;
}
}
$cxpos = ($currentxpos / $this->k);
$lmpos = ($this->lMargin + $this->cell_padding['L'] + $this->feps);
if ($this->inxobj) {
foreach ($this->xobjects[$this->xobjid]['annotations'] as $pak => $pac) {
if (($pac['y'] >= $minstartliney) AND (($pac['x'] * $this->k) >= ($currentxpos - $this->feps)) AND (($pac['x'] * $this->k) <= ($currentxpos + $this->feps))) {
if ($cxpos > $lmpos) {
$this->xobjects[$this->xobjid]['annotations'][$pak]['x'] += ($spacew / $this->k);
$this->xobjects[$this->xobjid]['annotations'][$pak]['w'] += (($spacewidth * $pac['numspaces']) / $this->k);
} else {
$this->xobjects[$this->xobjid]['annotations'][$pak]['w'] += (($spacewidth * $pac['numspaces']) / $this->k);
}
break;
}
}
} elseif (isset($this->PageAnnots[$this->page])) {
foreach ($this->PageAnnots[$this->page] as $pak => $pac) {
if (($pac['y'] >= $minstartliney) AND (($pac['x'] * $this->k) >= ($currentxpos - $this->feps)) AND (($pac['x'] * $this->k) <= ($currentxpos + $this->feps))) {
if ($cxpos > $lmpos) {
$this->PageAnnots[$this->page][$pak]['x'] += ($spacew / $this->k);
$this->PageAnnots[$this->page][$pak]['w'] += (($spacewidth * $pac['numspaces']) / $this->k);
} else {
$this->PageAnnots[$this->page][$pak]['w'] += (($spacewidth * $pac['numspaces']) / $this->k);
}
break;
}
}
}
}
$pmid = str_replace('x*#!#*x', '', $pmid);
if ($this->isUnicodeFont()) {
$spacew = $spacewidthu;
if ($this->font_stretching != 100) {
$spacew /= ($this->font_stretching / 100);
}
$pos = 0;
$pmid = preg_replace('/[\\\][\(]/x', '\\#!#OP#!#', $pmid);
$pmid = preg_replace('/[\\\][\)]/x', '\\#!#CP#!#', $pmid);
if (preg_match_all('/\[\(([^\)]*)\)\]/x', $pmid, $pamatch) > 0) {
foreach($pamatch[0] as $pk => $pmatch) {
$replace = $pamatch[1][$pk];
$replace = str_replace('#!#OP#!#', '(', $replace);
$replace = str_replace('#!#CP#!#', ')', $replace);
$newpmid = '[('.str_replace(chr(0).chr(32), ') '.sprintf('%F', $spacew).' (', $replace).')]';
$pos = strpos($pmid, $pmatch, $pos);
if ($pos !== FALSE) {
$pmid = substr_replace($pmid, $newpmid, $pos, strlen($pmatch));
}
++$pos;
}
unset($pamatch);
}
if ($this->inxobj) {
$this->xobjects[$this->xobjid]['outdata'] = $pstart."\n".$pmid."\n".$pend;
} else {
$this->setPageBuffer($startlinepage, $pstart."\n".$pmid."\n".$pend);
}
$endlinepos = strlen($pstart."\n".$pmid."\n");
} else {
if ($this->font_stretching != 100) {
$spacewidth /= ($this->font_stretching / 100);
}
$rs = sprintf('%F Tw', $spacewidth);
$pmid = preg_replace("/\[\(/x", $rs.' [(', $pmid);
if ($this->inxobj) {
$this->xobjects[$this->xobjid]['outdata'] = $pstart."\n".$pmid."\nBT 0 Tw ET\n".$pend;
} else {
$this->setPageBuffer($startlinepage, $pstart."\n".$pmid."\nBT 0 Tw ET\n".$pend);
}
$endlinepos = strlen($pstart."\n".$pmid."\nBT 0 Tw ET\n");
}
}
}
}
if (($t_x != 0) OR ($yshift < 0)) {
$trx = sprintf('1 0 0 1 %F %F cm', ($t_x * $this->k), ($yshift * $this->k));
$pstart .= "\nq\n".$trx."\n".$pmid."\nQ\n";
$endlinepos = strlen($pstart);
if ($this->inxobj) {
$this->xobjects[$this->xobjid]['outdata'] = $pstart.$pend;
foreach ($this->xobjects[$this->xobjid]['annotations'] as $pak => $pac) {
if ($pak >= $pask) {
$this->xobjects[$this->xobjid]['annotations'][$pak]['x'] += $t_x;
$this->xobjects[$this->xobjid]['annotations'][$pak]['y'] -= $yshift;
}
}
} else {
$this->setPageBuffer($startlinepage, $pstart.$pend);
if (isset($this->PageAnnots[$this->page])) {
foreach ($this->PageAnnots[$this->page] as $pak => $pac) {
if ($pak >= $pask) {
$this->PageAnnots[$this->page][$pak]['x'] += $t_x;
$this->PageAnnots[$this->page][$pak]['y'] -= $yshift;
}
}
}
}
$this->y -= $yshift;
}
}
$pbrk = $this->checkPageBreak($this->lasth);
$this->newline = false;
$startlinex = $this->x;
$startliney = $this->y;
if ($dom[$dom[$key]['parent']]['value'] == 'sup') {
$startliney -= ((0.3 * $this->FontSizePt) / $this->k);
} elseif ($dom[$dom[$key]['parent']]['value'] == 'sub') {
$startliney -= (($this->FontSizePt / 0.7) / $this->k);
} else {
$minstartliney = $startliney;
$maxbottomliney = ($this->y + $this->getCellHeight($fontsize / $this->k));
}
$startlinepage = $this->page;
if (isset($endlinepos) AND (!$pbrk)) {
$startlinepos = $endlinepos;
} else {
if ($this->inxobj) {
$startlinepos = strlen($this->xobjects[$this->xobjid]['outdata']);
} elseif (!$this->InFooter) {
if (isset($this->footerlen[$this->page])) {
$this->footerpos[$this->page] = $this->pagelen[$this->page] - $this->footerlen[$this->page];
} else {
$this->footerpos[$this->page] = $this->pagelen[$this->page];
}
$startlinepos = $this->footerpos[$this->page];
} else {
$startlinepos = $this->pagelen[$this->page];
}
}
unset($endlinepos);
$plalign = $lalign;
if (isset($this->PageAnnots[$this->page])) {
$pask = count($this->PageAnnots[$this->page]);
} else {
$pask = 0;
}
if (!($dom[$key]['tag'] AND !$dom[$key]['opening'] AND ($dom[$key]['value'] == 'table')
AND (isset($this->emptypagemrk[$this->page]))
AND ($this->emptypagemrk[$this->page] == $this->pagelen[$this->page]))) {
$this->SetFont($fontname, $fontstyle, $fontsize);
if ($wfill) {
$this->SetFillColorArray($this->bgcolor);
}
}
}
if (isset($opentagpos)) {
unset($opentagpos);
}
if ($dom[$key]['tag']) {
if ($dom[$key]['opening']) {
if (isset($dom[$key]['text-indent']) AND $dom[$key]['block']) {
$this->textindent = $dom[$key]['text-indent'];
$this->newline = true;
}
if (($dom[$key]['value'] == 'table') AND isset($dom[$key]['cols']) AND ($dom[$key]['cols'] > 0)) {
if ($this->rtl) {
$wtmp = $this->x - $this->lMargin;
} else {
$wtmp = $this->w - $this->rMargin - $this->x;
}
if (isset($dom[$key]['attribute']['cellspacing'])) {
$clsp = $this->getHTMLUnitToUnits($dom[$key]['attribute']['cellspacing'], 1, 'px');
$cellspacing = array('H' => $clsp, 'V' => $clsp);
} elseif (isset($dom[$key]['border-spacing'])) {
$cellspacing = $dom[$key]['border-spacing'];
} else {
$cellspacing = array('H' => 0, 'V' => 0);
}
if (isset($dom[$key]['width'])) {
$table_width = $this->getHTMLUnitToUnits($dom[$key]['width'], $wtmp, 'px');
} else {
$table_width = $wtmp;
}
$table_width -= (2 * $cellspacing['H']);
if (!$this->inthead) {
$this->y += $cellspacing['V'];
}
if ($this->rtl) {
$cellspacingx = -$cellspacing['H'];
} else {
$cellspacingx = $cellspacing['H'];
}
$table_columns_width = ($table_width - ($cellspacing['H'] * ($dom[$key]['cols'] - 1)));
$table_min_column_width = ($table_columns_width / $dom[$key]['cols']);
$table_colwidths = array_fill(0, $dom[$key]['cols'], $table_min_column_width);
}
if ($dom[$key]['value'] == 'tr') {
$colid = 0;
}
if (($dom[$key]['value'] == 'td') OR ($dom[$key]['value'] == 'th')) {
$trid = $dom[$key]['parent'];
$table_el = $dom[$trid]['parent'];
if (!isset($dom[$table_el]['cols'])) {
$dom[$table_el]['cols'] = $dom[$trid]['cols'];
}
$tdborder = 0;
if (isset($dom[$key]['border']) AND !empty($dom[$key]['border'])) {
$tdborder = $dom[$key]['border'];
}
$colspan = intval($dom[$key]['attribute']['colspan']);
if ($colspan <= 0) {
$colspan = 1;
}
$old_cell_padding = $this->cell_padding;
if (isset($dom[($dom[$trid]['parent'])]['attribute']['cellpadding'])) {
$crclpd = $this->getHTMLUnitToUnits($dom[($dom[$trid]['parent'])]['attribute']['cellpadding'], 1, 'px');
$current_cell_padding = array('L' => $crclpd, 'T' => $crclpd, 'R' => $crclpd, 'B' => $crclpd);
} elseif (isset($dom[($dom[$trid]['parent'])]['padding'])) {
$current_cell_padding = $dom[($dom[$trid]['parent'])]['padding'];
} else {
$current_cell_padding = array('L' => 0, 'T' => 0, 'R' => 0, 'B' => 0);
}
$this->cell_padding = $current_cell_padding;
if (isset($dom[$key]['height'])) {
$cellh = $this->getHTMLUnitToUnits($dom[$key]['height'], 0, 'px');
} else {
$cellh = 0;
}
if (isset($dom[$key]['content'])) {
$cell_content = $dom[$key]['content'];
} else {
$cell_content = ' ';
}
$tagtype = $dom[$key]['value'];
$parentid = $key;
while (($key < $maxel) AND (!(($dom[$key]['tag']) AND (!$dom[$key]['opening']) AND ($dom[$key]['value'] == $tagtype) AND ($dom[$key]['parent'] == $parentid)))) {
++$key;
}
if (!isset($dom[$trid]['startpage'])) {
$dom[$trid]['startpage'] = $this->page;
} else {
$this->setPage($dom[$trid]['startpage']);
}
if (!isset($dom[$trid]['startcolumn'])) {
$dom[$trid]['startcolumn'] = $this->current_column;
} elseif ($this->current_column != $dom[$trid]['startcolumn']) {
$tmpx = $this->x;
$this->selectColumn($dom[$trid]['startcolumn']);
$this->x = $tmpx;
}
if (!isset($dom[$trid]['starty'])) {
$dom[$trid]['starty'] = $this->y;
} else {
$this->y = $dom[$trid]['starty'];
}
if (!isset($dom[$trid]['startx'])) {
$dom[$trid]['startx'] = $this->x;
$this->x += $cellspacingx;
} else {
$this->x += ($cellspacingx / 2);
}
if (isset($dom[$parentid]['attribute']['rowspan'])) {
$rowspan = intval($dom[$parentid]['attribute']['rowspan']);
} else {
$rowspan = 1;
}
if (isset($dom[$table_el]['rowspans'])) {
$rsk = 0;
$rskmax = count($dom[$table_el]['rowspans']);
while ($rsk < $rskmax) {
$trwsp = $dom[$table_el]['rowspans'][$rsk];
$rsstartx = $trwsp['startx'];
$rsendx = $trwsp['endx'];
if ($trwsp['startpage'] < $this->page) {
if (($this->rtl) AND ($this->pagedim[$this->page]['orm'] != $this->pagedim[$trwsp['startpage']]['orm'])) {
$dl = ($this->pagedim[$this->page]['orm'] - $this->pagedim[$trwsp['startpage']]['orm']);
$rsstartx -= $dl;
$rsendx -= $dl;
} elseif ((!$this->rtl) AND ($this->pagedim[$this->page]['olm'] != $this->pagedim[$trwsp['startpage']]['olm'])) {
$dl = ($this->pagedim[$this->page]['olm'] - $this->pagedim[$trwsp['startpage']]['olm']);
$rsstartx += $dl;
$rsendx += $dl;
}
}
if (($trwsp['rowspan'] > 0)
AND ($rsstartx > ($this->x - $cellspacing['H'] - $current_cell_padding['L'] - $this->feps))
AND ($rsstartx < ($this->x + $cellspacing['H'] + $current_cell_padding['R'] + $this->feps))
AND (($trwsp['starty'] < ($this->y - $this->feps)) OR ($trwsp['startpage'] < $this->page) OR ($trwsp['startcolumn'] < $this->current_column))) {
$this->x = $rsendx + $cellspacingx;
$colid += $trwsp['colspan'];
if (($trwsp['rowspan'] == 1)
AND (isset($dom[$trid]['endy']))
AND (isset($dom[$trid]['endpage']))
AND (isset($dom[$trid]['endcolumn']))
AND ($trwsp['endpage'] == $dom[$trid]['endpage'])
AND ($trwsp['endcolumn'] == $dom[$trid]['endcolumn'])) {
$dom[$table_el]['rowspans'][$rsk]['endy'] = max($dom[$trid]['endy'], $trwsp['endy']);
$dom[$trid]['endy'] = $dom[$table_el]['rowspans'][$rsk]['endy'];
}
$rsk = 0;
} else {
++$rsk;
}
}
}
if (isset($dom[$parentid]['width'])) {
$cellw = $this->getHTMLUnitToUnits($dom[$parentid]['width'], $table_columns_width, 'px');
$tmpcw = ($cellw / $colspan);
for ($i = 0; $i < $colspan; ++$i) {
$table_colwidths[($colid + $i)] = $tmpcw;
}
} else {
$cellw = 0;
for ($i = 0; $i < $colspan; ++$i) {
$cellw += (isset($table_colwidths[($colid + $i)]) ? $table_colwidths[($colid + $i)] : 0);
}
}
$cellw += (($colspan - 1) * $cellspacing['H']);
$colid += $colspan;
if ($rowspan > 1) {
$trsid = array_push($dom[$table_el]['rowspans'], array('trid' => $trid, 'rowspan' => $rowspan, 'mrowspan' => $rowspan, 'colspan' => $colspan, 'startpage' => $this->page, 'startcolumn' => $this->current_column, 'startx' => $this->x, 'starty' => $this->y));
}
$cellid = array_push($dom[$trid]['cellpos'], array('startx' => $this->x));
if ($rowspan > 1) {
$dom[$trid]['cellpos'][($cellid - 1)]['rowspanid'] = ($trsid - 1);
}
if (isset($dom[$parentid]['bgcolor']) AND ($dom[$parentid]['bgcolor'] !== false)) {
$dom[$trid]['cellpos'][($cellid - 1)]['bgcolor'] = $dom[$parentid]['bgcolor'];
}
if (isset($tdborder) AND !empty($tdborder)) {
$dom[$trid]['cellpos'][($cellid - 1)]['border'] = $tdborder;
}
$prevLastH = $this->lasth;
if ($this->rtl) {
$this->colxshift['x'] = $this->w - $this->x - $this->rMargin;
} else {
$this->colxshift['x'] = $this->x - $this->lMargin;
}
$this->colxshift['s'] = $cellspacing;
$this->colxshift['p'] = $current_cell_padding;
$this->MultiCell($cellw, $cellh, $cell_content, false, $lalign, false, 2, '', '', true, 0, true, true, 0, 'T', false);
$this->colxshift = array('x' => 0, 's' => array('H' => 0, 'V' => 0), 'p' => array('L' => 0, 'T' => 0, 'R' => 0, 'B' => 0));
$this->lasth = $prevLastH;
$this->cell_padding = $old_cell_padding;
$dom[$trid]['cellpos'][($cellid - 1)]['endx'] = $this->x;
if ($rowspan <= 1) {
if (isset($dom[$trid]['endy'])) {
if (($this->page == $dom[$trid]['endpage']) AND ($this->current_column == $dom[$trid]['endcolumn'])) {
$dom[$trid]['endy'] = max($this->y, $dom[$trid]['endy']);
} elseif (($this->page > $dom[$trid]['endpage']) OR ($this->current_column > $dom[$trid]['endcolumn'])) {
$dom[$trid]['endy'] = $this->y;
}
} else {
$dom[$trid]['endy'] = $this->y;
}
if (isset($dom[$trid]['endpage'])) {
$dom[$trid]['endpage'] = max($this->page, $dom[$trid]['endpage']);
} else {
$dom[$trid]['endpage'] = $this->page;
}
if (isset($dom[$trid]['endcolumn'])) {
$dom[$trid]['endcolumn'] = max($this->current_column, $dom[$trid]['endcolumn']);
} else {
$dom[$trid]['endcolumn'] = $this->current_column;
}
} else {
$dom[$table_el]['rowspans'][($trsid - 1)]['endx'] = $this->x;
$dom[$table_el]['rowspans'][($trsid - 1)]['endy'] = $this->y;
$dom[$table_el]['rowspans'][($trsid - 1)]['endpage'] = $this->page;
$dom[$table_el]['rowspans'][($trsid - 1)]['endcolumn'] = $this->current_column;
}
if (isset($dom[$table_el]['rowspans'])) {
foreach ($dom[$table_el]['rowspans'] as $k => $trwsp) {
if ($trwsp['rowspan'] > 0) {
if (isset($dom[$trid]['endpage'])) {
if (($trwsp['endpage'] == $dom[$trid]['endpage']) AND ($trwsp['endcolumn'] == $dom[$trid]['endcolumn'])) {
$dom[$table_el]['rowspans'][$k]['endy'] = max($dom[$trid]['endy'], $trwsp['endy']);
} elseif (($trwsp['endpage'] < $dom[$trid]['endpage']) OR ($trwsp['endcolumn'] < $dom[$trid]['endcolumn'])) {
$dom[$table_el]['rowspans'][$k]['endy'] = $dom[$trid]['endy'];
$dom[$table_el]['rowspans'][$k]['endpage'] = $dom[$trid]['endpage'];
$dom[$table_el]['rowspans'][$k]['endcolumn'] = $dom[$trid]['endcolumn'];
} else {
$dom[$trid]['endy'] = $this->pagedim[$dom[$trid]['endpage']]['hk'] - $this->pagedim[$dom[$trid]['endpage']]['bm'];
}
}
}
}
}
$this->x += ($cellspacingx / 2);
} else {
if (!isset($opentagpos)) {
if ($this->inxobj) {
$opentagpos = strlen($this->xobjects[$this->xobjid]['outdata']);
} elseif (!$this->InFooter) {
if (isset($this->footerlen[$this->page])) {
$this->footerpos[$this->page] = $this->pagelen[$this->page] - $this->footerlen[$this->page];
} else {
$this->footerpos[$this->page] = $this->pagelen[$this->page];
}
$opentagpos = $this->footerpos[$this->page];
}
}
$dom = $this->openHTMLTagHandler($dom, $key, $cell);
}
} else {
$prev_numpages = $this->numpages;
$old_bordermrk = $this->bordermrk[$this->page];
$dom = $this->closeHTMLTagHandler($dom, $key, $cell, $maxbottomliney);
if ($this->bordermrk[$this->page] > $old_bordermrk) {
$startlinepos += ($this->bordermrk[$this->page] - $old_bordermrk);
}
if ($prev_numpages > $this->numpages) {
$startlinepage = $this->page;
}
}
} elseif (strlen($dom[$key]['value']) > 0) {
if (!TCPDF_STATIC::empty_string($this->lispacer) AND ($this->lispacer != '^')) {
$this->SetFont($pfontname, $pfontstyle, $pfontsize);
$this->resetLastH();
$minstartliney = $this->y;
$maxbottomliney = ($startliney + $this->getCellHeight($this->FontSize));
if (is_numeric($pfontsize) AND ($pfontsize > 0)) {
$this->putHtmlListBullet($this->listnum, $this->lispacer, $pfontsize);
}
$this->SetFont($curfontname, $curfontstyle, $curfontsize);
$this->resetLastH();
if (is_numeric($pfontsize) AND ($pfontsize > 0) AND is_numeric($curfontsize) AND ($curfontsize > 0) AND ($pfontsize != $curfontsize)) {
$pfontascent = $this->getFontAscent($pfontname, $pfontstyle, $pfontsize);
$pfontdescent = $this->getFontDescent($pfontname, $pfontstyle, $pfontsize);
$this->y += ($this->getCellHeight(($pfontsize - $curfontsize) / $this->k) + $pfontascent - $curfontascent - $pfontdescent + $curfontdescent) / 2;
$minstartliney = min($this->y, $minstartliney);
$maxbottomliney = max(($this->y + $this->getCellHeight($pfontsize / $this->k)), $maxbottomliney);
}
}
$this->htmlvspace = 0;
if ((!$this->premode) AND $this->isRTLTextDir()) {
$lsp = '';
$rsp = '';
if (preg_match('/^('.$this->re_space['p'].'+)/'.$this->re_space['m'], $dom[$key]['value'], $matches)) {
$lsp = $matches[1];
}
if (preg_match('/('.$this->re_space['p'].'+)$/'.$this->re_space['m'], $dom[$key]['value'], $matches)) {
$rsp = $matches[1];
}
$dom[$key]['value'] = $rsp.$this->stringTrim($dom[$key]['value']).$lsp;
}
if ($newline) {
if (!$this->premode) {
$prelen = strlen($dom[$key]['value']);
if ($this->isRTLTextDir()) {
$dom[$key]['value'] = $this->stringRightTrim($dom[$key]['value']);
} else {
$dom[$key]['value'] = $this->stringLeftTrim($dom[$key]['value']);
}
$postlen = strlen($dom[$key]['value']);
if (($postlen == 0) AND ($prelen > 0)) {
$dom[$key]['trimmed_space'] = true;
}
}
$newline = false;
$firstblock = true;
} else {
$firstblock = false;
$dom[$key]['value'] = preg_replace('/^'.$this->re_space['p'].'+$/'.$this->re_space['m'], chr(32), $dom[$key]['value']);
}
$strrest = '';
if ($this->rtl) {
$this->x -= $this->textindent;
} else {
$this->x += $this->textindent;
}
if (!isset($dom[$key]['trimmed_space']) OR !$dom[$key]['trimmed_space']) {
$strlinelen = $this->GetStringWidth($dom[$key]['value']);
if (!empty($this->HREF) AND (isset($this->HREF['url']))) {
$hrefcolor = '';
if (isset($dom[($dom[$key]['parent'])]['fgcolor']) AND ($dom[($dom[$key]['parent'])]['fgcolor'] !== false)) {
$hrefcolor = $dom[($dom[$key]['parent'])]['fgcolor'];
}
$hrefstyle = -1;
if (isset($dom[($dom[$key]['parent'])]['fontstyle']) AND ($dom[($dom[$key]['parent'])]['fontstyle'] !== false)) {
$hrefstyle = $dom[($dom[$key]['parent'])]['fontstyle'];
}
$strrest = $this->addHtmlLink($this->HREF['url'], $dom[$key]['value'], $wfill, true, $hrefcolor, $hrefstyle, true);
} else {
$wadj = 0;
if ($this->rtl) {
$cwa = ($this->x - $this->lMargin);
} else {
$cwa = ($this->w - $this->rMargin - $this->x);
}
if (($strlinelen < $cwa) AND (isset($dom[($key + 1)])) AND ($dom[($key + 1)]['tag']) AND (!$dom[($key + 1)]['block'])) {
$nkey = ($key + 1);
$write_block = true;
$same_textdir = true;
$tmp_fontname = $this->FontFamily;
$tmp_fontstyle = $this->FontStyle;
$tmp_fontsize = $this->FontSizePt;
while ($write_block AND isset($dom[$nkey])) {
if ($dom[$nkey]['tag']) {
if ($dom[$nkey]['block']) {
$write_block = false;
}
$tmp_fontname = isset($dom[$nkey]['fontname']) ? $dom[$nkey]['fontname'] : $this->FontFamily;
$tmp_fontstyle = isset($dom[$nkey]['fontstyle']) ? $dom[$nkey]['fontstyle'] : $this->FontStyle;
$tmp_fontsize = isset($dom[$nkey]['fontsize']) ? $dom[$nkey]['fontsize'] : $this->FontSizePt;
$same_textdir = ($dom[$nkey]['dir'] == $dom[$key]['dir']);
} else {
$nextstr = TCPDF_STATIC::pregSplit('/'.$this->re_space['p'].'+/', $this->re_space['m'], $dom[$nkey]['value']);
if (isset($nextstr[0]) AND $same_textdir) {
$wadj += $this->GetStringWidth($nextstr[0], $tmp_fontname, $tmp_fontstyle, $tmp_fontsize);
if (isset($nextstr[1])) {
$write_block = false;
}
}
}
++$nkey;
}
}
if (($wadj > 0) AND (($strlinelen + $wadj) >= $cwa)) {
$wadj = 0;
$nextstr = TCPDF_STATIC::pregSplit('/'.$this->re_space['p'].'/', $this->re_space['m'], $dom[$key]['value']);
$numblks = count($nextstr);
if ($numblks > 1) {
$wadj = ($cwa - $strlinelen + $this->GetStringWidth($nextstr[($numblks - 1)]));
} else {
$wadj = $this->GetStringWidth($nextstr[0]);
}
}
if (($wadj > 0) AND (($this->rtl AND ($this->tmprtl === 'L')) OR (!$this->rtl AND ($this->tmprtl === 'R')))) {
$reverse_dir = true;
$this->rtl = !$this->rtl;
$revshift = ($strlinelen + $wadj + 0.000001);
if ($this->rtl) {
$this->x += $revshift;
} else {
$this->x -= $revshift;
}
$xws = $this->x;
}
$strrest = $this->Write($this->lasth, $dom[$key]['value'], '', $wfill, '', false, 0, true, $firstblock, 0, $wadj);
if ($reverse_dir AND ($wadj == 0)) {
$this->x = $xws;
$this->rtl = !$this->rtl;
$reverse_dir = false;
}
}
}
$this->textindent = 0;
if (strlen($strrest) > 0) {
$this->newline = true;
if ($strrest == $dom[$key]['value']) {
++$loop;
} else {
$loop = 0;
}
$dom[$key]['value'] = $strrest;
if ($cell) {
if ($this->rtl) {
$this->x -= $this->cell_padding['R'];
} else {
$this->x += $this->cell_padding['L'];
}
}
if ($loop < 3) {
--$key;
}
} else {
$loop = 0;
if ($this->font_spacing > 0) {
if ($this->rtl) {
$this->x -= $this->font_spacing;
} else {
$this->x += $this->font_spacing;
}
}
}
}
++$key;
if (isset($dom[$key]['tag']) AND $dom[$key]['tag'] AND (!isset($dom[$key]['opening']) OR !$dom[$key]['opening']) AND isset($dom[($dom[$key]['parent'])]['attribute']['nobr']) AND ($dom[($dom[$key]['parent'])]['attribute']['nobr'] == 'true')) {
if ((!$undo) AND (($this->y < $this->start_transaction_y) OR (($dom[$key]['value'] == 'tr') AND ($dom[($dom[$key]['parent'])]['endy'] < $this->start_transaction_y)))) {
$this->rollbackTransaction(true);
foreach ($this_method_vars as $vkey => $vval) {
$$vkey = $vval;
}
if (!empty($dom[$key]['thead'])) {
$this->inthead = true;
}
$pre_y = $this->y;
if ((!$this->checkPageBreak($this->PageBreakTrigger + 1)) AND ($this->y < $pre_y)) {
$startliney = $this->y;
}
$undo = true;
} else {
$undo = false;
}
}
}
if (isset($startlinex)) {
$yshift = ($minstartliney - $startliney);
if (($yshift > 0) OR ($this->page > $startlinepage)) {
$yshift = 0;
}
$t_x = 0;
$linew = abs($this->endlinex - $startlinex);
if ($this->inxobj) {
$pstart = substr($this->xobjects[$this->xobjid]['outdata'], 0, $startlinepos);
if (isset($opentagpos)) {
$midpos = $opentagpos;
} else {
$midpos = 0;
}
if ($midpos > 0) {
$pmid = substr($this->xobjects[$this->xobjid]['outdata'], $startlinepos, ($midpos - $startlinepos));
$pend = substr($this->xobjects[$this->xobjid]['outdata'], $midpos);
} else {
$pmid = substr($this->xobjects[$this->xobjid]['outdata'], $startlinepos);
$pend = '';
}
} else {
$pstart = substr($this->getPageBuffer($startlinepage), 0, $startlinepos);
if (isset($opentagpos) AND isset($this->footerlen[$startlinepage]) AND (!$this->InFooter)) {
$this->footerpos[$startlinepage] = $this->pagelen[$startlinepage] - $this->footerlen[$startlinepage];
$midpos = min($opentagpos, $this->footerpos[$startlinepage]);
} elseif (isset($opentagpos)) {
$midpos = $opentagpos;
} elseif (isset($this->footerlen[$startlinepage]) AND (!$this->InFooter)) {
$this->footerpos[$startlinepage] = $this->pagelen[$startlinepage] - $this->footerlen[$startlinepage];
$midpos = $this->footerpos[$startlinepage];
} else {
$midpos = 0;
}
if ($midpos > 0) {
$pmid = substr($this->getPageBuffer($startlinepage), $startlinepos, ($midpos - $startlinepos));
$pend = substr($this->getPageBuffer($startlinepage), $midpos);
} else {
$pmid = substr($this->getPageBuffer($startlinepage), $startlinepos);
$pend = '';
}
}
if ((isset($plalign) AND ((($plalign == 'C') OR (($plalign == 'R') AND (!$this->rtl)) OR (($plalign == 'L') AND ($this->rtl)))))) {
$tw = $w;
if ($this->lMargin != $prevlMargin) {
$tw += ($prevlMargin - $this->lMargin);
}
if ($this->rMargin != $prevrMargin) {
$tw += ($prevrMargin - $this->rMargin);
}
$one_space_width = $this->GetStringWidth(chr(32));
$no = 0;
if ($this->isRTLTextDir()) {
$pos1 = TCPDF_STATIC::revstrpos($pmid, '[(');
if ($pos1 > 0) {
$pos1 = intval($pos1);
if ($this->isUnicodeFont()) {
$pos2 = intval(TCPDF_STATIC::revstrpos($pmid, '[('.chr(0).chr(32)));
$spacelen = 2;
} else {
$pos2 = intval(TCPDF_STATIC::revstrpos($pmid, '[('.chr(32)));
$spacelen = 1;
}
if ($pos1 == $pos2) {
$pmid = substr($pmid, 0, ($pos1 + 2)).substr($pmid, ($pos1 + 2 + $spacelen));
if (substr($pmid, $pos1, 4) == '[()]') {
$linew -= $one_space_width;
} elseif ($pos1 == strpos($pmid, '[(')) {
$no = 1;
}
}
}
} else {
$pos1 = TCPDF_STATIC::revstrpos($pmid, ')]');
if ($pos1 > 0) {
$pos1 = intval($pos1);
if ($this->isUnicodeFont()) {
$pos2 = intval(TCPDF_STATIC::revstrpos($pmid, chr(0).chr(32).')]')) + 2;
$spacelen = 2;
} else {
$pos2 = intval(TCPDF_STATIC::revstrpos($pmid, chr(32).')]')) + 1;
$spacelen = 1;
}
if ($pos1 == $pos2) {
$pmid = substr($pmid, 0, ($pos1 - $spacelen)).substr($pmid, $pos1);
$linew -= $one_space_width;
}
}
}
$mdiff = ($tw - $linew);
if ($plalign == 'C') {
if ($this->rtl) {
$t_x = -($mdiff / 2);
} else {
$t_x = ($mdiff / 2);
}
} elseif ($plalign == 'R') {
$t_x = $mdiff;
} elseif ($plalign == 'L') {
$t_x = -$mdiff;
}
}
if (($t_x != 0) OR ($yshift < 0)) {
$trx = sprintf('1 0 0 1 %F %F cm', ($t_x * $this->k), ($yshift * $this->k));
$pstart .= "\nq\n".$trx."\n".$pmid."\nQ\n";
$endlinepos = strlen($pstart);
if ($this->inxobj) {
$this->xobjects[$this->xobjid]['outdata'] = $pstart.$pend;
foreach ($this->xobjects[$this->xobjid]['annotations'] as $pak => $pac) {
if ($pak >= $pask) {
$this->xobjects[$this->xobjid]['annotations'][$pak]['x'] += $t_x;
$this->xobjects[$this->xobjid]['annotations'][$pak]['y'] -= $yshift;
}
}
} else {
$this->setPageBuffer($startlinepage, $pstart.$pend);
if (isset($this->PageAnnots[$this->page])) {
foreach ($this->PageAnnots[$this->page] as $pak => $pac) {
if ($pak >= $pask) {
$this->PageAnnots[$this->page][$pak]['x'] += $t_x;
$this->PageAnnots[$this->page][$pak]['y'] -= $yshift;
}
}
}
}
$this->y -= $yshift;
$yshift = 0;
}
}
$this->setGraphicVars($gvars);
if ($this->num_columns > 1) {
$this->selectColumn();
} elseif ($this->page > $prevPage) {
$this->lMargin = $this->pagedim[$this->page]['olm'];
$this->rMargin = $this->pagedim[$this->page]['orm'];
}
$this->cell_height_ratio = $prev_cell_height_ratio;
$this->listnum = $prev_listnum;
$this->listordered = $prev_listordered;
$this->listcount = $prev_listcount;
$this->lispacer = $prev_lispacer;
if ($ln AND (!($cell AND ($dom[$key-1]['value'] == 'table')))) {
$this->Ln($this->lasth);
if (($this->y < $maxbottomliney) AND ($startlinepage == $this->page)) {
$this->y = $maxbottomliney;
}
}
unset($dom);
}
protected function openHTMLTagHandler($dom, $key, $cell) {
$tag = $dom[$key];
$parent = $dom[($dom[$key]['parent'])];
$firsttag = ($key == 1);
if (isset($tag['dir'])) {
$this->setTempRTL($tag['dir']);
} else {
$this->tmprtl = false;
}
if ($tag['block']) {
$hbz = 0;
$hb = 0;
if (isset($this->tagvspaces[$tag['value']][0]['h']) AND ($this->tagvspaces[$tag['value']][0]['h'] >= 0)) {
$cur_h = $this->tagvspaces[$tag['value']][0]['h'];
} elseif (isset($tag['fontsize'])) {
$cur_h = $this->getCellHeight($tag['fontsize'] / $this->k);
} else {
$cur_h = $this->getCellHeight($this->FontSize);
}
if (isset($this->tagvspaces[$tag['value']][0]['n'])) {
$on = $this->tagvspaces[$tag['value']][0]['n'];
} elseif (preg_match('/[h][0-9]/', $tag['value']) > 0) {
$on = 0.6;
} else {
$on = 1;
}
if ((!isset($this->tagvspaces[$tag['value']])) AND (in_array($tag['value'], array('div', 'dt', 'dd', 'li', 'br', 'hr')))) {
$hb = 0;
} else {
$hb = ($on * $cur_h);
}
if (($this->htmlvspace <= 0) AND ($on > 0)) {
if (isset($parent['fontsize'])) {
$hbz = (($parent['fontsize'] / $this->k) * $this->cell_height_ratio);
} else {
$hbz = $this->getCellHeight($this->FontSize);
}
}
if (isset($dom[($key - 1)]) AND ($dom[($key - 1)]['value'] == 'table')) {
$hbz = 0;
}
$hbc = 0;
if (isset($this->tagvspaces[$tag['value']][1]['h']) AND ($this->tagvspaces[$tag['value']][1]['h'] >= 0)) {
$pre_h = $this->tagvspaces[$tag['value']][1]['h'];
} elseif (isset($parent['fontsize'])) {
$pre_h = $this->getCellHeight($parent['fontsize'] / $this->k);
} else {
$pre_h = $this->getCellHeight($this->FontSize);
}
if (isset($this->tagvspaces[$tag['value']][1]['n'])) {
$cn = $this->tagvspaces[$tag['value']][1]['n'];
} elseif (preg_match('/[h][0-9]/', $tag['value']) > 0) {
$cn = 0.6;
} else {
$cn = 1;
}
if (isset($this->tagvspaces[$tag['value']][1])) {
$hbc = ($cn * $pre_h);
}
}
switch($tag['value']) {
case 'table': {
$cp = 0;
$cs = 0;
$dom[$key]['rowspans'] = array();
if (!isset($dom[$key]['attribute']['nested']) OR ($dom[$key]['attribute']['nested'] != 'true')) {
$this->htmlvspace = 0;
if (!TCPDF_STATIC::empty_string($dom[$key]['thead'])) {
$this->thead = $dom[$key]['thead'];
if (!isset($this->theadMargins) OR (empty($this->theadMargins))) {
$this->theadMargins = array();
$this->theadMargins['cell_padding'] = $this->cell_padding;
$this->theadMargins['lmargin'] = $this->lMargin;
$this->theadMargins['rmargin'] = $this->rMargin;
$this->theadMargins['page'] = $this->page;
$this->theadMargins['cell'] = $cell;
$this->theadMargins['gvars'] = $this->getGraphicVars();
}
}
}
$dom[$key]['old_cell_padding'] = $this->cell_padding;
if (isset($tag['attribute']['cellpadding'])) {
$pad = $this->getHTMLUnitToUnits($tag['attribute']['cellpadding'], 1, 'px');
$this->SetCellPadding($pad);
} elseif (isset($tag['padding'])) {
$this->cell_padding = $tag['padding'];
}
if (isset($tag['attribute']['cellspacing'])) {
$cs = $this->getHTMLUnitToUnits($tag['attribute']['cellspacing'], 1, 'px');
} elseif (isset($tag['border-spacing'])) {
$cs = $tag['border-spacing']['V'];
}
$prev_y = $this->y;
if ($this->checkPageBreak(((2 * $cp) + (2 * $cs) + $this->lasth), '', false) OR ($this->y < $prev_y)) {
$this->inthead = true;
$this->checkPageBreak($this->PageBreakTrigger + 1);
}
break;
}
case 'tr': {
$dom[$key]['cellpos'] = array();
break;
}
case 'hr': {
if ((isset($tag['height'])) AND ($tag['height'] != '')) {
$hrHeight = $this->getHTMLUnitToUnits($tag['height'], 1, 'px');
} else {
$hrHeight = $this->GetLineWidth();
}
$this->addHTMLVertSpace($hbz, max($hb, ($hrHeight / 2)), $cell, $firsttag);
$x = $this->GetX();
$y = $this->GetY();
$wtmp = $this->w - $this->lMargin - $this->rMargin;
if ($cell) {
$wtmp -= ($this->cell_padding['L'] + $this->cell_padding['R']);
}
if ((isset($tag['width'])) AND ($tag['width'] != '')) {
$hrWidth = $this->getHTMLUnitToUnits($tag['width'], $wtmp, 'px');
} else {
$hrWidth = $wtmp;
}
$prevlinewidth = $this->GetLineWidth();
$this->SetLineWidth($hrHeight);
$this->Line($x, $y, $x + $hrWidth, $y);
$this->SetLineWidth($prevlinewidth);
$this->addHTMLVertSpace(max($hbc, ($hrHeight / 2)), 0, $cell, !isset($dom[($key + 1)]));
break;
}
case 'a': {
if (array_key_exists('href', $tag['attribute'])) {
$this->HREF['url'] = $tag['attribute']['href'];
}
break;
}
case 'img': {
if (!empty($tag['attribute']['src'])) {
if ($tag['attribute']['src'][0] === '@') {
$tag['attribute']['src'] = '@'.base64_decode(substr($tag['attribute']['src'], 1));
$type = '';
} else {
$type = TCPDF_IMAGES::getImageFileType($tag['attribute']['src']);
}
if (!isset($tag['width'])) {
$tag['width'] = 0;
}
if (!isset($tag['height'])) {
$tag['height'] = 0;
}
$tag['attribute']['align'] = 'bottom';
switch($tag['attribute']['align']) {
case 'top': {
$align = 'T';
break;
}
case 'middle': {
$align = 'M';
break;
}
case 'bottom': {
$align = 'B';
break;
}
default: {
$align = 'B';
break;
}
}
$prevy = $this->y;
$xpos = $this->x;
$imglink = '';
if (isset($this->HREF['url']) AND !TCPDF_STATIC::empty_string($this->HREF['url'])) {
$imglink = $this->HREF['url'];
if ($imglink[0] == '#') {
$lnkdata = explode(',', $imglink);
if (isset($lnkdata[0])) {
$page = intval(substr($lnkdata[0], 1));
if (empty($page) OR ($page <= 0)) {
$page = $this->page;
}
if (isset($lnkdata[1]) AND (strlen($lnkdata[1]) > 0)) {
$lnky = floatval($lnkdata[1]);
} else {
$lnky = 0;
}
$imglink = $this->AddLink();
$this->SetLink($imglink, $lnky, $page);
}
}
}
$border = 0;
if (isset($tag['border']) AND !empty($tag['border'])) {
$border = $tag['border'];
}
$iw = '';
if (isset($tag['width'])) {
$iw = $this->getHTMLUnitToUnits($tag['width'], ($tag['fontsize'] / $this->k), 'px', false);
}
$ih = '';
if (isset($tag['height'])) {
$ih = $this->getHTMLUnitToUnits($tag['height'], ($tag['fontsize'] / $this->k), 'px', false);
}
if (($type == 'eps') OR ($type == 'ai')) {
$this->ImageEps($tag['attribute']['src'], $xpos, $this->y, $iw, $ih, $imglink, true, $align, '', $border, true);
} elseif ($type == 'svg') {
$this->ImageSVG($tag['attribute']['src'], $xpos, $this->y, $iw, $ih, $imglink, $align, '', $border, true);
} else {
$this->Image($tag['attribute']['src'], $xpos, $this->y, $iw, $ih, '', $imglink, $align, false, 300, '', false, false, $border, false, false, true);
}
switch($align) {
case 'T': {
$this->y = $prevy;
break;
}
case 'M': {
$this->y = (($this->img_rb_y + $prevy - ($this->getCellHeight($tag['fontsize'] / $this->k))) / 2);
break;
}
case 'B': {
$this->y = $this->img_rb_y - ($this->getCellHeight($tag['fontsize'] / $this->k) - ($this->getFontDescent($tag['fontname'], $tag['fontstyle'], $tag['fontsize']) * $this->cell_height_ratio));
break;
}
}
}
break;
}
case 'dl': {
++$this->listnum;
if ($this->listnum == 1) {
$this->addHTMLVertSpace($hbz, $hb, $cell, $firsttag);
} else {
$this->addHTMLVertSpace(0, 0, $cell, $firsttag);
}
break;
}
case 'dt': {
$this->addHTMLVertSpace($hbz, $hb, $cell, $firsttag);
break;
}
case 'dd': {
if ($this->rtl) {
$this->rMargin += $this->listindent;
} else {
$this->lMargin += $this->listindent;
}
++$this->listindentlevel;
$this->addHTMLVertSpace($hbz, $hb, $cell, $firsttag);
break;
}
case 'ul':
case 'ol': {
++$this->listnum;
if ($tag['value'] == 'ol') {
$this->listordered[$this->listnum] = true;
} else {
$this->listordered[$this->listnum] = false;
}
if (isset($tag['attribute']['start'])) {
$this->listcount[$this->listnum] = intval($tag['attribute']['start']) - 1;
} else {
$this->listcount[$this->listnum] = 0;
}
if ($this->rtl) {
$this->rMargin += $this->listindent;
$this->x -= $this->listindent;
} else {
$this->lMargin += $this->listindent;
$this->x += $this->listindent;
}
++$this->listindentlevel;
if ($this->listnum == 1) {
if ($key > 1) {
$this->addHTMLVertSpace($hbz, $hb, $cell, $firsttag);
}
} else {
$this->addHTMLVertSpace(0, 0, $cell, $firsttag);
}
break;
}
case 'li': {
if ($key > 2) {
$this->addHTMLVertSpace($hbz, $hb, $cell, $firsttag);
}
if ($this->listordered[$this->listnum]) {
if (isset($parent['attribute']['type']) AND !TCPDF_STATIC::empty_string($parent['attribute']['type'])) {
$this->lispacer = $parent['attribute']['type'];
} elseif (isset($parent['listtype']) AND !TCPDF_STATIC::empty_string($parent['listtype'])) {
$this->lispacer = $parent['listtype'];
} elseif (isset($this->lisymbol) AND !TCPDF_STATIC::empty_string($this->lisymbol)) {
$this->lispacer = $this->lisymbol;
} else {
$this->lispacer = '#';
}
++$this->listcount[$this->listnum];
if (isset($tag['attribute']['value'])) {
$this->listcount[$this->listnum] = intval($tag['attribute']['value']);
}
} else {
if (isset($parent['attribute']['type']) AND !TCPDF_STATIC::empty_string($parent['attribute']['type'])) {
$this->lispacer = $parent['attribute']['type'];
} elseif (isset($parent['listtype']) AND !TCPDF_STATIC::empty_string($parent['listtype'])) {
$this->lispacer = $parent['listtype'];
} elseif (isset($this->lisymbol) AND !TCPDF_STATIC::empty_string($this->lisymbol)) {
$this->lispacer = $this->lisymbol;
} else {
$this->lispacer = '!';
}
}
break;
}
case 'blockquote': {
if ($this->rtl) {
$this->rMargin += $this->listindent;
} else {
$this->lMargin += $this->listindent;
}
++$this->listindentlevel;
$this->addHTMLVertSpace($hbz, $hb, $cell, $firsttag);
break;
}
case 'br': {
$this->addHTMLVertSpace($hbz, $hb, $cell, $firsttag);
break;
}
case 'div': {
$this->addHTMLVertSpace($hbz, $hb, $cell, $firsttag);
break;
}
case 'p': {
$this->addHTMLVertSpace($hbz, $hb, $cell, $firsttag);
break;
}
case 'pre': {
$this->addHTMLVertSpace($hbz, $hb, $cell, $firsttag);
$this->premode = true;
break;
}
case 'sup': {
$this->SetXY($this->GetX(), $this->GetY() - ((0.7 * $this->FontSizePt) / $this->k));
break;
}
case 'sub': {
$this->SetXY($this->GetX(), $this->GetY() + ((0.3 * $this->FontSizePt) / $this->k));
break;
}
case 'h1':
case 'h2':
case 'h3':
case 'h4':
case 'h5':
case 'h6': {
$this->addHTMLVertSpace($hbz, $hb, $cell, $firsttag);
break;
}
case 'form': {
if (isset($tag['attribute']['action'])) {
$this->form_action = $tag['attribute']['action'];
} else {
$this->Error('Please explicitly set action attribute path!');
}
if (isset($tag['attribute']['enctype'])) {
$this->form_enctype = $tag['attribute']['enctype'];
} else {
$this->form_enctype = 'application/x-www-form-urlencoded';
}
if (isset($tag['attribute']['method'])) {
$this->form_mode = $tag['attribute']['method'];
} else {
$this->form_mode = 'post';
}
break;
}
case 'input': {
if (isset($tag['attribute']['name']) AND !TCPDF_STATIC::empty_string($tag['attribute']['name'])) {
$name = $tag['attribute']['name'];
} else {
break;
}
$prop = array();
$opt = array();
if (isset($tag['attribute']['readonly']) AND !TCPDF_STATIC::empty_string($tag['attribute']['readonly'])) {
$prop['readonly'] = true;
}
if (isset($tag['attribute']['value']) AND !TCPDF_STATIC::empty_string($tag['attribute']['value'])) {
$value = $tag['attribute']['value'];
}
if (isset($tag['attribute']['maxlength']) AND !TCPDF_STATIC::empty_string($tag['attribute']['maxlength'])) {
$opt['maxlen'] = intval($tag['attribute']['maxlength']);
}
$h = $this->getCellHeight($this->FontSize);
if (isset($tag['attribute']['size']) AND !TCPDF_STATIC::empty_string($tag['attribute']['size'])) {
$w = intval($tag['attribute']['size']) * $this->GetStringWidth(chr(32)) * 2;
} else {
$w = $h;
}
if (isset($tag['attribute']['checked']) AND (($tag['attribute']['checked'] == 'checked') OR ($tag['attribute']['checked'] == 'true'))) {
$checked = true;
} else {
$checked = false;
}
if (isset($tag['align'])) {
switch ($tag['align']) {
case 'C': {
$opt['q'] = 1;
break;
}
case 'R': {
$opt['q'] = 2;
break;
}
case 'L':
default: {
break;
}
}
}
switch ($tag['attribute']['type']) {
case 'text': {
if (isset($value)) {
$opt['v'] = $value;
}
$this->TextField($name, $w, $h, $prop, $opt, '', '', false);
break;
}
case 'password': {
if (isset($value)) {
$opt['v'] = $value;
}
$prop['password'] = 'true';
$this->TextField($name, $w, $h, $prop, $opt, '', '', false);
break;
}
case 'checkbox': {
if (!isset($value)) {
break;
}
$this->CheckBox($name, $w, $checked, $prop, $opt, $value, '', '', false);
break;
}
case 'radio': {
if (!isset($value)) {
break;
}
$this->RadioButton($name, $w, $prop, $opt, $value, $checked, '', '', false);
break;
}
case 'submit': {
if (!isset($value)) {
$value = 'submit';
}
$w = $this->GetStringWidth($value) * 1.5;
$h *= 1.6;
$prop = array('lineWidth'=>1, 'borderStyle'=>'beveled', 'fillColor'=>array(196, 196, 196), 'strokeColor'=>array(255, 255, 255));
$action = array();
$action['S'] = 'SubmitForm';
$action['F'] = $this->form_action;
if ($this->form_enctype != 'FDF') {
$action['Flags'] = array('ExportFormat');
}
if ($this->form_mode == 'get') {
$action['Flags'] = array('GetMethod');
}
$this->Button($name, $w, $h, $value, $action, $prop, $opt, '', '', false);
break;
}
case 'reset': {
if (!isset($value)) {
$value = 'reset';
}
$w = $this->GetStringWidth($value) * 1.5;
$h *= 1.6;
$prop = array('lineWidth'=>1, 'borderStyle'=>'beveled', 'fillColor'=>array(196, 196, 196), 'strokeColor'=>array(255, 255, 255));
$this->Button($name, $w, $h, $value, array('S'=>'ResetForm'), $prop, $opt, '', '', false);
break;
}
case 'file': {
$prop['fileSelect'] = 'true';
$this->TextField($name, $w, $h, $prop, $opt, '', '', false);
if (!isset($value)) {
$value = '*';
}
$w = $this->GetStringWidth($value) * 2;
$h *= 1.2;
$prop = array('lineWidth'=>1, 'borderStyle'=>'beveled', 'fillColor'=>array(196, 196, 196), 'strokeColor'=>array(255, 255, 255));
$jsaction = 'var f=this.getField(\''.$name.'\'); f.browseForFileToSubmit();';
$this->Button('FB_'.$name, $w, $h, $value, $jsaction, $prop, $opt, '', '', false);
break;
}
case 'hidden': {
if (isset($value)) {
$opt['v'] = $value;
}
$opt['f'] = array('invisible', 'hidden');
$this->TextField($name, 0, 0, $prop, $opt, '', '', false);
break;
}
case 'image': {
if (isset($tag['attribute']['src']) AND !TCPDF_STATIC::empty_string($tag['attribute']['src'])) {
$img = $tag['attribute']['src'];
} else {
break;
}
$value = 'img';
if (isset($tag['attribute']['onclick']) AND !empty($tag['attribute']['onclick'])) {
$jsaction = $tag['attribute']['onclick'];
} else {
$jsaction = '';
}
$this->Button($name, $w, $h, $value, $jsaction, $prop, $opt, '', '', false);
break;
}
case 'button': {
if (!isset($value)) {
$value = ' ';
}
$w = $this->GetStringWidth($value) * 1.5;
$h *= 1.6;
$prop = array('lineWidth'=>1, 'borderStyle'=>'beveled', 'fillColor'=>array(196, 196, 196), 'strokeColor'=>array(255, 255, 255));
if (isset($tag['attribute']['onclick']) AND !empty($tag['attribute']['onclick'])) {
$jsaction = $tag['attribute']['onclick'];
} else {
$jsaction = '';
}
$this->Button($name, $w, $h, $value, $jsaction, $prop, $opt, '', '', false);
break;
}
}
break;
}
case 'textarea': {
$prop = array();
$opt = array();
if (isset($tag['attribute']['readonly']) AND !TCPDF_STATIC::empty_string($tag['attribute']['readonly'])) {
$prop['readonly'] = true;
}
if (isset($tag['attribute']['name']) AND !TCPDF_STATIC::empty_string($tag['attribute']['name'])) {
$name = $tag['attribute']['name'];
} else {
break;
}
if (isset($tag['attribute']['value']) AND !TCPDF_STATIC::empty_string($tag['attribute']['value'])) {
$opt['v'] = $tag['attribute']['value'];
}
if (isset($tag['attribute']['cols']) AND !TCPDF_STATIC::empty_string($tag['attribute']['cols'])) {
$w = intval($tag['attribute']['cols']) * $this->GetStringWidth(chr(32)) * 2;
} else {
$w = 40;
}
if (isset($tag['attribute']['rows']) AND !TCPDF_STATIC::empty_string($tag['attribute']['rows'])) {
$h = intval($tag['attribute']['rows']) * $this->getCellHeight($this->FontSize);
} else {
$h = 10;
}
$prop['multiline'] = 'true';
$this->TextField($name, $w, $h, $prop, $opt, '', '', false);
break;
}
case 'select': {
$h = $this->getCellHeight($this->FontSize);
if (isset($tag['attribute']['size']) AND !TCPDF_STATIC::empty_string($tag['attribute']['size'])) {
$h *= ($tag['attribute']['size'] + 1);
}
$prop = array();
$opt = array();
if (isset($tag['attribute']['name']) AND !TCPDF_STATIC::empty_string($tag['attribute']['name'])) {
$name = $tag['attribute']['name'];
} else {
break;
}
$w = 0;
if (isset($tag['attribute']['opt']) AND !TCPDF_STATIC::empty_string($tag['attribute']['opt'])) {
$options = explode('#!NwL!#', $tag['attribute']['opt']);
$values = array();
foreach ($options as $val) {
if (strpos($val, '#!TaB!#') !== false) {
$opts = explode('#!TaB!#', $val);
$values[] = $opts;
$w = max($w, $this->GetStringWidth($opts[1]));
} else {
$values[] = $val;
$w = max($w, $this->GetStringWidth($val));
}
}
} else {
break;
}
$w *= 2;
if (isset($tag['attribute']['multiple']) AND ($tag['attribute']['multiple']='multiple')) {
$prop['multipleSelection'] = 'true';
$this->ListBox($name, $w, $h, $values, $prop, $opt, '', '', false);
} else {
$this->ComboBox($name, $w, $h, $values, $prop, $opt, '', '', false);
}
break;
}
case 'tcpdf': {
if (defined('K_TCPDF_CALLS_IN_HTML') AND (K_TCPDF_CALLS_IN_HTML === true)) {
if (isset($tag['attribute']['method'])) {
$tcpdf_method = $tag['attribute']['method'];
if (method_exists($this, $tcpdf_method)) {
if (isset($tag['attribute']['params']) AND (!empty($tag['attribute']['params']))) {
$params = $this->unserializeTCPDFtagParameters($tag['attribute']['params']);
call_user_func_array(array($this, $tcpdf_method), $params);
} else {
$this->$tcpdf_method();
}
$this->newline = true;
}
}
}
break;
}
default: {
break;
}
}
$bordertags = array('blockquote','br','dd','dl','div','dt','h1','h2','h3','h4','h5','h6','hr','li','ol','p','pre','ul','tcpdf','table');
if (in_array($tag['value'], $bordertags)) {
$dom[$key]['borderposition'] = $this->getBorderStartPosition();
}
if ($dom[$key]['self'] AND isset($dom[$key]['attribute']['pagebreakafter'])) {
$pba = $dom[$key]['attribute']['pagebreakafter'];
if (($pba == 'true') OR ($pba == 'left') OR ($pba == 'right')) {
$this->checkPageBreak($this->PageBreakTrigger + 1);
}
if ((($pba == 'left') AND (((!$this->rtl) AND (($this->page % 2) == 0)) OR (($this->rtl) AND (($this->page % 2) != 0))))
OR (($pba == 'right') AND (((!$this->rtl) AND (($this->page % 2) != 0)) OR (($this->rtl) AND (($this->page % 2) == 0))))) {
$this->checkPageBreak($this->PageBreakTrigger + 1);
}
}
return $dom;
}
protected function closeHTMLTagHandler($dom, $key, $cell, $maxbottomliney=0) {
$tag = $dom[$key];
$parent = $dom[($dom[$key]['parent'])];
$lasttag = ((!isset($dom[($key + 1)])) OR ((!isset($dom[($key + 2)])) AND ($dom[($key + 1)]['value'] == 'marker')));
$in_table_head = false;
if ($this->rtl) {
$xmax = $this->w;
} else {
$xmax = 0;
}
if ($tag['block']) {
$hbz = 0;
$hb = 0;
if (isset($this->tagvspaces[$tag['value']][1]['h']) AND ($this->tagvspaces[$tag['value']][1]['h'] >= 0)) {
$pre_h = $this->tagvspaces[$tag['value']][1]['h'];
} elseif (isset($parent['fontsize'])) {
$pre_h = $this->getCellHeight($parent['fontsize'] / $this->k);
} else {
$pre_h = $this->getCellHeight($this->FontSize);
}
if (isset($this->tagvspaces[$tag['value']][1]['n'])) {
$cn = $this->tagvspaces[$tag['value']][1]['n'];
} elseif (preg_match('/[h][0-9]/', $tag['value']) > 0) {
$cn = 0.6;
} else {
$cn = 1;
}
if ((!isset($this->tagvspaces[$tag['value']])) AND ($tag['value'] == 'div')) {
$hb = 0;
} else {
$hb = ($cn * $pre_h);
}
if ($maxbottomliney > $this->PageBreakTrigger) {
$hbz = $this->getCellHeight($this->FontSize);
} elseif ($this->y < $maxbottomliney) {
$hbz = ($maxbottomliney - $this->y);
}
}
switch($tag['value']) {
case 'tr': {
$table_el = $dom[($dom[$key]['parent'])]['parent'];
if (!isset($parent['endy'])) {
$dom[($dom[$key]['parent'])]['endy'] = $this->y;
$parent['endy'] = $this->y;
}
if (!isset($parent['endpage'])) {
$dom[($dom[$key]['parent'])]['endpage'] = $this->page;
$parent['endpage'] = $this->page;
}
if (!isset($parent['endcolumn'])) {
$dom[($dom[$key]['parent'])]['endcolumn'] = $this->current_column;
$parent['endcolumn'] = $this->current_column;
}
if (isset($dom[$table_el]['rowspans'])) {
foreach ($dom[$table_el]['rowspans'] as $k => $trwsp) {
$dom[$table_el]['rowspans'][$k]['rowspan'] -= 1;
if ($dom[$table_el]['rowspans'][$k]['rowspan'] == 0) {
if (($dom[$table_el]['rowspans'][$k]['endpage'] == $parent['endpage']) AND ($dom[$table_el]['rowspans'][$k]['endcolumn'] == $parent['endcolumn'])) {
$dom[($dom[$key]['parent'])]['endy'] = max($dom[$table_el]['rowspans'][$k]['endy'], $parent['endy']);
} elseif (($dom[$table_el]['rowspans'][$k]['endpage'] > $parent['endpage']) OR ($dom[$table_el]['rowspans'][$k]['endcolumn'] > $parent['endcolumn'])) {
$dom[($dom[$key]['parent'])]['endy'] = $dom[$table_el]['rowspans'][$k]['endy'];
$dom[($dom[$key]['parent'])]['endpage'] = $dom[$table_el]['rowspans'][$k]['endpage'];
$dom[($dom[$key]['parent'])]['endcolumn'] = $dom[$table_el]['rowspans'][$k]['endcolumn'];
}
}
}
foreach ($dom[$table_el]['rowspans'] as $k => $trwsp) {
if ($dom[$table_el]['rowspans'][$k]['rowspan'] == 0) {
$dom[$table_el]['rowspans'][$k]['endpage'] = max($dom[$table_el]['rowspans'][$k]['endpage'], $dom[($dom[$key]['parent'])]['endpage']);
$dom[($dom[$key]['parent'])]['endpage'] = $dom[$table_el]['rowspans'][$k]['endpage'];
$dom[$table_el]['rowspans'][$k]['endcolumn'] = max($dom[$table_el]['rowspans'][$k]['endcolumn'], $dom[($dom[$key]['parent'])]['endcolumn']);
$dom[($dom[$key]['parent'])]['endcolumn'] = $dom[$table_el]['rowspans'][$k]['endcolumn'];
$dom[$table_el]['rowspans'][$k]['endy'] = max($dom[$table_el]['rowspans'][$k]['endy'], $dom[($dom[$key]['parent'])]['endy']);
$dom[($dom[$key]['parent'])]['endy'] = $dom[$table_el]['rowspans'][$k]['endy'];
}
}
foreach ($dom[$table_el]['rowspans'] as $k => $trwsp) {
if ($dom[$table_el]['rowspans'][$k]['rowspan'] == 0) {
$dom[$table_el]['rowspans'][$k]['endpage'] = $dom[($dom[$key]['parent'])]['endpage'];
$dom[$table_el]['rowspans'][$k]['endcolumn'] = $dom[($dom[$key]['parent'])]['endcolumn'];
$dom[$table_el]['rowspans'][$k]['endy'] = $dom[($dom[$key]['parent'])]['endy'];
}
}
}
$prev_page = $this->page;
$this->setPage($dom[($dom[$key]['parent'])]['endpage']);
if ($this->num_columns > 1) {
if (($prev_page < $this->page)
AND ((($this->current_column == 0) AND ($dom[($dom[$key]['parent'])]['endcolumn'] == ($this->num_columns - 1)))
OR ($this->current_column == $dom[($dom[$key]['parent'])]['endcolumn']))) {
$this->selectColumn(0);
$dom[($dom[$key]['parent'])]['endcolumn'] = 0;
$dom[($dom[$key]['parent'])]['endy'] = $this->y;
} else {
$this->selectColumn($dom[($dom[$key]['parent'])]['endcolumn']);
$this->y = $dom[($dom[$key]['parent'])]['endy'];
}
} else {
$this->y = $dom[($dom[$key]['parent'])]['endy'];
}
if (isset($dom[$table_el]['attribute']['cellspacing'])) {
$this->y += $this->getHTMLUnitToUnits($dom[$table_el]['attribute']['cellspacing'], 1, 'px');
} elseif (isset($dom[$table_el]['border-spacing'])) {
$this->y += $dom[$table_el]['border-spacing']['V'];
}
$this->Ln(0, $cell);
if ($this->current_column == $parent['startcolumn']) {
$this->x = $parent['startx'];
}
if ($this->page > $parent['startpage']) {
if (($this->rtl) AND ($this->pagedim[$this->page]['orm'] != $this->pagedim[$parent['startpage']]['orm'])) {
$this->x -= ($this->pagedim[$this->page]['orm'] - $this->pagedim[$parent['startpage']]['orm']);
} elseif ((!$this->rtl) AND ($this->pagedim[$this->page]['olm'] != $this->pagedim[$parent['startpage']]['olm'])) {
$this->x += ($this->pagedim[$this->page]['olm'] - $this->pagedim[$parent['startpage']]['olm']);
}
}
break;
}
case 'tablehead':
$in_table_head = true;
$this->inthead = false;
case 'table': {
$table_el = $parent;
if (isset($table_el['attribute']['border']) AND ($table_el['attribute']['border'] > 0)) {
$border = array('LTRB' => array('width' => $this->getCSSBorderWidth($table_el['attribute']['border']), 'cap'=>'square', 'join'=>'miter', 'dash'=> 0, 'color'=>array(0,0,0)));
} else {
$border = 0;
}
$default_border = $border;
foreach ($dom[($dom[$key]['parent'])]['trids'] as $j => $trkey) {
if (isset($dom[($dom[$key]['parent'])]['rowspans'])) {
foreach ($dom[($dom[$key]['parent'])]['rowspans'] as $k => $trwsp) {
if (isset($prevtrkey) AND ($trwsp['trid'] == $prevtrkey) AND ($trwsp['mrowspan'] > 0)) {
$dom[($dom[$key]['parent'])]['rowspans'][$k]['trid'] = $trkey;
}
if ($dom[($dom[$key]['parent'])]['rowspans'][$k]['trid'] == $trkey) {
$dom[($dom[$key]['parent'])]['rowspans'][$k]['mrowspan'] -= 1;
}
}
}
if (isset($prevtrkey) AND ($dom[$trkey]['startpage'] > $dom[$prevtrkey]['endpage'])) {
$pgendy = $this->pagedim[$dom[$prevtrkey]['endpage']]['hk'] - $this->pagedim[$dom[$prevtrkey]['endpage']]['bm'];
$dom[$prevtrkey]['endy'] = $pgendy;
if (isset($dom[($dom[$key]['parent'])]['rowspans'])) {
foreach ($dom[($dom[$key]['parent'])]['rowspans'] as $k => $trwsp) {
if (($trwsp['trid'] == $prevtrkey) AND ($trwsp['mrowspan'] >= 0) AND ($trwsp['endpage'] == $dom[$prevtrkey]['endpage'])) {
$dom[($dom[$key]['parent'])]['rowspans'][$k]['endy'] = $pgendy;
$dom[($dom[$key]['parent'])]['rowspans'][$k]['mrowspan'] = -1;
}
}
}
}
$prevtrkey = $trkey;
$table_el = $dom[($dom[$key]['parent'])];
}
if (count($table_el['trids']) > 0) {
unset($xmax);
}
foreach ($table_el['trids'] as $j => $trkey) {
$parent = $dom[$trkey];
if (!isset($xmax)) {
$xmax = $parent['cellpos'][(count($parent['cellpos']) - 1)]['endx'];
}
foreach ($parent['cellpos'] as $k => $cellpos) {
if (isset($cellpos['rowspanid']) AND ($cellpos['rowspanid'] >= 0)) {
$cellpos['startx'] = $table_el['rowspans'][($cellpos['rowspanid'])]['startx'];
$cellpos['endx'] = $table_el['rowspans'][($cellpos['rowspanid'])]['endx'];
$endy = $table_el['rowspans'][($cellpos['rowspanid'])]['endy'];
$startpage = $table_el['rowspans'][($cellpos['rowspanid'])]['startpage'];
$endpage = $table_el['rowspans'][($cellpos['rowspanid'])]['endpage'];
$startcolumn = $table_el['rowspans'][($cellpos['rowspanid'])]['startcolumn'];
$endcolumn = $table_el['rowspans'][($cellpos['rowspanid'])]['endcolumn'];
} else {
$endy = $parent['endy'];
$startpage = $parent['startpage'];
$endpage = $parent['endpage'];
$startcolumn = $parent['startcolumn'];
$endcolumn = $parent['endcolumn'];
}
if ($this->num_columns == 0) {
$this->num_columns = 1;
}
if (isset($cellpos['border'])) {
$border = $cellpos['border'];
}
if (isset($cellpos['bgcolor']) AND ($cellpos['bgcolor']) !== false) {
$this->SetFillColorArray($cellpos['bgcolor']);
$fill = true;
} else {
$fill = false;
}
$x = $cellpos['startx'];
$y = $parent['starty'];
$starty = $y;
$w = abs($cellpos['endx'] - $cellpos['startx']);
$border_start = TCPDF_STATIC::getBorderMode($border, $position='start', $this->opencell);
$border_end = TCPDF_STATIC::getBorderMode($border, $position='end', $this->opencell);
$border_middle = TCPDF_STATIC::getBorderMode($border, $position='middle', $this->opencell);
for ($page = $startpage; $page <= $endpage; ++$page) {
$ccode = '';
$this->setPage($page);
if ($this->num_columns < 2) {
$this->x = $x;
$this->y = $this->tMargin;
}
if ($page > $startpage) {
if (($this->rtl) AND ($this->pagedim[$page]['orm'] != $this->pagedim[$startpage]['orm'])) {
$this->x -= ($this->pagedim[$page]['orm'] - $this->pagedim[$startpage]['orm']);
} elseif ((!$this->rtl) AND ($this->pagedim[$page]['olm'] != $this->pagedim[$startpage]['olm'])) {
$this->x += ($this->pagedim[$page]['olm'] - $this->pagedim[$startpage]['olm']);
}
}
if ($startpage == $endpage) {
$deltacol = 0;
$deltath = 0;
for ($column = $startcolumn; $column <= $endcolumn; ++$column) {
$this->selectColumn($column);
if ($startcolumn == $endcolumn) {
$cborder = $border;
$h = $endy - $parent['starty'];
$this->y = $y;
$this->x = $x;
} elseif ($column == $startcolumn) {
$cborder = $border_start;
$this->y = $starty;
$this->x = $x;
$h = $this->h - $this->y - $this->bMargin;
if ($this->rtl) {
$deltacol = $this->x + $this->rMargin - $this->w;
} else {
$deltacol = $this->x - $this->lMargin;
}
} elseif ($column == $endcolumn) {
$cborder = $border_end;
if (isset($this->columns[$column]['th']['\''.$page.'\''])) {
$this->y = $this->columns[$column]['th']['\''.$page.'\''];
}
$this->x += $deltacol;
$h = $endy - $this->y;
} else {
$cborder = $border_middle;
if (isset($this->columns[$column]['th']['\''.$page.'\''])) {
$this->y = $this->columns[$column]['th']['\''.$page.'\''];
}
$this->x += $deltacol;
$h = $this->h - $this->y - $this->bMargin;
}
$ccode .= $this->getCellCode($w, $h, '', $cborder, 1, '', $fill, '', 0, true)."\n";
}
} elseif ($page == $startpage) {
$deltacol = 0;
$deltath = 0;
for ($column = $startcolumn; $column < $this->num_columns; ++$column) {
$this->selectColumn($column);
if ($column == $startcolumn) {
$cborder = $border_start;
$this->y = $starty;
$this->x = $x;
$h = $this->h - $this->y - $this->bMargin;
if ($this->rtl) {
$deltacol = $this->x + $this->rMargin - $this->w;
} else {
$deltacol = $this->x - $this->lMargin;
}
} else {
$cborder = $border_middle;
if (isset($this->columns[$column]['th']['\''.$page.'\''])) {
$this->y = $this->columns[$column]['th']['\''.$page.'\''];
}
$this->x += $deltacol;
$h = $this->h - $this->y - $this->bMargin;
}
$ccode .= $this->getCellCode($w, $h, '', $cborder, 1, '', $fill, '', 0, true)."\n";
}
} elseif ($page == $endpage) {
$deltacol = 0;
$deltath = 0;
for ($column = 0; $column <= $endcolumn; ++$column) {
$this->selectColumn($column);
if ($column == $endcolumn) {
$cborder = $border_end;
if (isset($this->columns[$column]['th']['\''.$page.'\''])) {
$this->y = $this->columns[$column]['th']['\''.$page.'\''];
}
$this->x += $deltacol;
$h = $endy - $this->y;
} else {
$cborder = $border_middle;
if (isset($this->columns[$column]['th']['\''.$page.'\''])) {
$this->y = $this->columns[$column]['th']['\''.$page.'\''];
}
$this->x += $deltacol;
$h = $this->h - $this->y - $this->bMargin;
}
$ccode .= $this->getCellCode($w, $h, '', $cborder, 1, '', $fill, '', 0, true)."\n";
}
} else {
$deltacol = 0;
$deltath = 0;
for ($column = 0; $column < $this->num_columns; ++$column) {
$this->selectColumn($column);
$cborder = $border_middle;
if (isset($this->columns[$column]['th']['\''.$page.'\''])) {
$this->y = $this->columns[$column]['th']['\''.$page.'\''];
}
$this->x += $deltacol;
$h = $this->h - $this->y - $this->bMargin;
$ccode .= $this->getCellCode($w, $h, '', $cborder, 1, '', $fill, '', 0, true)."\n";
}
}
if (!empty($cborder) OR !empty($fill)) {
$offsetlen = strlen($ccode);
if ($this->inxobj) {
if (end($this->xobjects[$this->xobjid]['transfmrk']) !== false) {
$pagemarkkey = key($this->xobjects[$this->xobjid]['transfmrk']);
$pagemark = $this->xobjects[$this->xobjid]['transfmrk'][$pagemarkkey];
$this->xobjects[$this->xobjid]['transfmrk'][$pagemarkkey] += $offsetlen;
} else {
$pagemark = $this->xobjects[$this->xobjid]['intmrk'];
$this->xobjects[$this->xobjid]['intmrk'] += $offsetlen;
}
$pagebuff = $this->xobjects[$this->xobjid]['outdata'];
$pstart = substr($pagebuff, 0, $pagemark);
$pend = substr($pagebuff, $pagemark);
$this->xobjects[$this->xobjid]['outdata'] = $pstart.$ccode.$pend;
} else {
if (end($this->transfmrk[$this->page]) !== false) {
$pagemarkkey = key($this->transfmrk[$this->page]);
$pagemark = $this->transfmrk[$this->page][$pagemarkkey];
} elseif ($this->InFooter) {
$pagemark = $this->footerpos[$this->page];
} else {
$pagemark = $this->intmrk[$this->page];
}
$pagebuff = $this->getPageBuffer($this->page);
$pstart = substr($pagebuff, 0, $pagemark);
$pend = substr($pagebuff, $pagemark);
$this->setPageBuffer($this->page, $pstart.$ccode.$pend);
}
}
}
$border = $default_border;
}
if (isset($table_el['attribute']['cellspacing'])) {
$this->y += $this->getHTMLUnitToUnits($table_el['attribute']['cellspacing'], 1, 'px');
} elseif (isset($table_el['border-spacing'])) {
$this->y += $table_el['border-spacing']['V'];
}
$this->Ln(0, $cell);
$this->x = $parent['startx'];
if ($endpage > $startpage) {
if (($this->rtl) AND ($this->pagedim[$endpage]['orm'] != $this->pagedim[$startpage]['orm'])) {
$this->x += ($this->pagedim[$endpage]['orm'] - $this->pagedim[$startpage]['orm']);
} elseif ((!$this->rtl) AND ($this->pagedim[$endpage]['olm'] != $this->pagedim[$startpage]['olm'])) {
$this->x += ($this->pagedim[$endpage]['olm'] - $this->pagedim[$startpage]['olm']);
}
}
}
if (!$in_table_head) {
$this->cell_padding = $table_el['old_cell_padding'];
$this->resetLastH();
if (($this->page == ($this->numpages - 1)) AND ($this->pageopen[$this->numpages])) {
$plendiff = ($this->pagelen[$this->numpages] - $this->emptypagemrk[$this->numpages]);
if (($plendiff > 0) AND ($plendiff < 60)) {
$pagediff = substr($this->getPageBuffer($this->numpages), $this->emptypagemrk[$this->numpages], $plendiff);
if (substr($pagediff, 0, 5) == 'BT /F') {
$plendiff = 0;
}
}
if ($plendiff == 0) {
$this->deletePage($this->numpages);
}
}
if (isset($this->theadMargins['top'])) {
$this->tMargin = $this->theadMargins['top'];
}
if (!isset($table_el['attribute']['nested']) OR ($table_el['attribute']['nested'] != 'true')) {
$this->thead = '';
$this->theadMargins = array();
$this->pagedim[$this->page]['tm'] = $this->tMargin;
}
}
$parent = $table_el;
break;
}
case 'a': {
$this->HREF = array();
break;
}
case 'sup': {
$this->SetXY($this->GetX(), $this->GetY() + ((0.7 * $parent['fontsize']) / $this->k));
break;
}
case 'sub': {
$this->SetXY($this->GetX(), $this->GetY() - ((0.3 * $parent['fontsize']) / $this->k));
break;
}
case 'div': {
$this->addHTMLVertSpace($hbz, $hb, $cell, false, $lasttag);
break;
}
case 'blockquote': {
if ($this->rtl) {
$this->rMargin -= $this->listindent;
} else {
$this->lMargin -= $this->listindent;
}
--$this->listindentlevel;
$this->addHTMLVertSpace($hbz, $hb, $cell, false, $lasttag);
break;
}
case 'p': {
$this->addHTMLVertSpace($hbz, $hb, $cell, false, $lasttag);
break;
}
case 'pre': {
$this->addHTMLVertSpace($hbz, $hb, $cell, false, $lasttag);
$this->premode = false;
break;
}
case 'dl': {
--$this->listnum;
if ($this->listnum <= 0) {
$this->listnum = 0;
$this->addHTMLVertSpace($hbz, $hb, $cell, false, $lasttag);
} else {
$this->addHTMLVertSpace(0, 0, $cell, false, $lasttag);
}
$this->resetLastH();
break;
}
case 'dt': {
$this->lispacer = '';
$this->addHTMLVertSpace(0, 0, $cell, false, $lasttag);
break;
}
case 'dd': {
$this->lispacer = '';
if ($this->rtl) {
$this->rMargin -= $this->listindent;
} else {
$this->lMargin -= $this->listindent;
}
--$this->listindentlevel;
$this->addHTMLVertSpace(0, 0, $cell, false, $lasttag);
break;
}
case 'ul':
case 'ol': {
--$this->listnum;
$this->lispacer = '';
if ($this->rtl) {
$this->rMargin -= $this->listindent;
} else {
$this->lMargin -= $this->listindent;
}
--$this->listindentlevel;
if ($this->listnum <= 0) {
$this->listnum = 0;
$this->addHTMLVertSpace($hbz, $hb, $cell, false, $lasttag);
} else {
$this->addHTMLVertSpace(0, 0, $cell, false, $lasttag);
}
$this->resetLastH();
break;
}
case 'li': {
$this->lispacer = '';
$this->addHTMLVertSpace(0, 0, $cell, false, $lasttag);
break;
}
case 'h1':
case 'h2':
case 'h3':
case 'h4':
case 'h5':
case 'h6': {
$this->addHTMLVertSpace($hbz, $hb, $cell, false, $lasttag);
break;
}
case 'form': {
$this->form_action = '';
$this->form_enctype = 'application/x-www-form-urlencoded';
break;
}
default : {
break;
}
}
$this->drawHTMLTagBorder($parent, $xmax);
if (isset($dom[($dom[$key]['parent'])]['attribute']['pagebreakafter'])) {
$pba = $dom[($dom[$key]['parent'])]['attribute']['pagebreakafter'];
if (($pba == 'true') OR ($pba == 'left') OR ($pba == 'right')) {
$this->checkPageBreak($this->PageBreakTrigger + 1);
}
if ((($pba == 'left') AND (((!$this->rtl) AND (($this->page % 2) == 0)) OR (($this->rtl) AND (($this->page % 2) != 0))))
OR (($pba == 'right') AND (((!$this->rtl) AND (($this->page % 2) != 0)) OR (($this->rtl) AND (($this->page % 2) == 0))))) {
$this->checkPageBreak($this->PageBreakTrigger + 1);
}
}
$this->tmprtl = false;
return $dom;
}
protected function addHTMLVertSpace($hbz=0, $hb=0, $cell=false, $firsttag=false, $lasttag=false) {
if ($firsttag) {
$this->Ln(0, $cell);
$this->htmlvspace = 0;
return;
}
if ($lasttag) {
$this->Ln($hbz, $cell);
$this->htmlvspace = 0;
return;
}
if ($hb < $this->htmlvspace) {
$hd = 0;
} else {
$hd = $hb - $this->htmlvspace;
$this->htmlvspace = $hb;
}
$this->Ln(($hbz + $hd), $cell);
}
protected function getBorderStartPosition() {
if ($this->rtl) {
$xmax = $this->lMargin;
} else {
$xmax = $this->w - $this->rMargin;
}
return array('page' => $this->page, 'column' => $this->current_column, 'x' => $this->x, 'y' => $this->y, 'xmax' => $xmax);
}
protected function drawHTMLTagBorder($tag, $xmax) {
if (!isset($tag['borderposition'])) {
return;
}
$prev_x = $this->x;
$prev_y = $this->y;
$prev_lasth = $this->lasth;
$border = 0;
$fill = false;
$this->lasth = 0;
if (isset($tag['border']) AND !empty($tag['border'])) {
$border = $tag['border'];
if (!TCPDF_STATIC::empty_string($this->thead) AND (!$this->inthead)) {
$border = TCPDF_STATIC::getBorderMode($border, $position='middle', $this->opencell);
}
}
if (isset($tag['bgcolor']) AND ($tag['bgcolor'] !== false)) {
$old_bgcolor = $this->bgcolor;
$this->SetFillColorArray($tag['bgcolor']);
$fill = true;
}
if (!$border AND !$fill) {
return;
}
if (isset($tag['attribute']['cellspacing'])) {
$clsp = $this->getHTMLUnitToUnits($tag['attribute']['cellspacing'], 1, 'px');
$cellspacing = array('H' => $clsp, 'V' => $clsp);
} elseif (isset($tag['border-spacing'])) {
$cellspacing = $tag['border-spacing'];
} else {
$cellspacing = array('H' => 0, 'V' => 0);
}
if (($tag['value'] != 'table') AND (is_array($border)) AND (!empty($border))) {
$border['mode'] = 'ext';
}
if ($this->rtl) {
if ($xmax >= $tag['borderposition']['x']) {
$xmax = $tag['borderposition']['xmax'];
}
$w = ($tag['borderposition']['x'] - $xmax);
} else {
if ($xmax <= $tag['borderposition']['x']) {
$xmax = $tag['borderposition']['xmax'];
}
$w = ($xmax - $tag['borderposition']['x']);
}
if ($w <= 0) {
return;
}
$w += $cellspacing['H'];
$startpage = $tag['borderposition']['page'];
$startcolumn = $tag['borderposition']['column'];
$x = $tag['borderposition']['x'];
$y = $tag['borderposition']['y'];
$endpage = $this->page;
$starty = $tag['borderposition']['y'] - $cellspacing['V'];
$currentY = $this->y;
$this->x = $x;
$endcolumn = $this->current_column;
if ($this->num_columns == 0) {
$this->num_columns = 1;
}
$border_start = TCPDF_STATIC::getBorderMode($border, $position='start', $this->opencell);
$border_end = TCPDF_STATIC::getBorderMode($border, $position='end', $this->opencell);
$border_middle = TCPDF_STATIC::getBorderMode($border, $position='middle', $this->opencell);
$temp_page_regions = $this->page_regions;
$this->page_regions = array();
for ($page = $startpage; $page <= $endpage; ++$page) {
$ccode = '';
$this->setPage($page);
if ($this->num_columns < 2) {
$this->x = $x;
$this->y = $this->tMargin;
}
if ($page > $startpage) {
if (($this->rtl) AND ($this->pagedim[$page]['orm'] != $this->pagedim[$startpage]['orm'])) {
$this->x -= ($this->pagedim[$page]['orm'] - $this->pagedim[$startpage]['orm']);
} elseif ((!$this->rtl) AND ($this->pagedim[$page]['olm'] != $this->pagedim[$startpage]['olm'])) {
$this->x += ($this->pagedim[$page]['olm'] - $this->pagedim[$startpage]['olm']);
}
}
if ($startpage == $endpage) {
for ($column = $startcolumn; $column <= $endcolumn; ++$column) {
$this->selectColumn($column);
if ($startcolumn == $endcolumn) {
$cborder = $border;
$h = ($currentY - $y) + $cellspacing['V'];
$this->y = $starty;
} elseif ($column == $startcolumn) {
$cborder = $border_start;
$this->y = $starty;
$h = $this->h - $this->y - $this->bMargin;
} elseif ($column == $endcolumn) {
$cborder = $border_end;
$h = $currentY - $this->y;
} else {
$cborder = $border_middle;
$h = $this->h - $this->y - $this->bMargin;
}
$ccode .= $this->getCellCode($w, $h, '', $cborder, 1, '', $fill, '', 0, true)."\n";
}
} elseif ($page == $startpage) {
for ($column = $startcolumn; $column < $this->num_columns; ++$column) {
$this->selectColumn($column);
if ($column == $startcolumn) {
$cborder = $border_start;
$this->y = $starty;
$h = $this->h - $this->y - $this->bMargin;
} else {
$cborder = $border_middle;
$h = $this->h - $this->y - $this->bMargin;
}
$ccode .= $this->getCellCode($w, $h, '', $cborder, 1, '', $fill, '', 0, true)."\n";
}
} elseif ($page == $endpage) {
for ($column = 0; $column <= $endcolumn; ++$column) {
$this->selectColumn($column);
if ($column == $endcolumn) {
$cborder = $border_end;
$h = $currentY - $this->y;
} else {
$cborder = $border_middle;
$h = $this->h - $this->y - $this->bMargin;
}
$ccode .= $this->getCellCode($w, $h, '', $cborder, 1, '', $fill, '', 0, true)."\n";
}
} else {
for ($column = 0; $column < $this->num_columns; ++$column) {
$this->selectColumn($column);
$cborder = $border_middle;
$h = $this->h - $this->y - $this->bMargin;
$ccode .= $this->getCellCode($w, $h, '', $cborder, 1, '', $fill, '', 0, true)."\n";
}
}
if ($cborder OR $fill) {
$offsetlen = strlen($ccode);
if ($this->inxobj) {
if (end($this->xobjects[$this->xobjid]['transfmrk']) !== false) {
$pagemarkkey = key($this->xobjects[$this->xobjid]['transfmrk']);
$pagemark = $this->xobjects[$this->xobjid]['transfmrk'][$pagemarkkey];
$this->xobjects[$this->xobjid]['transfmrk'][$pagemarkkey] += $offsetlen;
} else {
$pagemark = $this->xobjects[$this->xobjid]['intmrk'];
$this->xobjects[$this->xobjid]['intmrk'] += $offsetlen;
}
$pagebuff = $this->xobjects[$this->xobjid]['outdata'];
$pstart = substr($pagebuff, 0, $pagemark);
$pend = substr($pagebuff, $pagemark);
$this->xobjects[$this->xobjid]['outdata'] = $pstart.$ccode.$pend;
} else {
if (end($this->transfmrk[$this->page]) !== false) {
$pagemarkkey = key($this->transfmrk[$this->page]);
$pagemark = $this->transfmrk[$this->page][$pagemarkkey];
} elseif ($this->InFooter) {
$pagemark = $this->footerpos[$this->page];
} else {
$pagemark = $this->intmrk[$this->page];
}
$pagebuff = $this->getPageBuffer($this->page);
$pstart = substr($pagebuff, 0, $pagemark);
$pend = substr($pagebuff, $pagemark);
$this->setPageBuffer($this->page, $pstart.$ccode.$pend);
$this->bordermrk[$this->page] += $offsetlen;
$this->cntmrk[$this->page] += $offsetlen;
}
}
}
$this->page_regions = $temp_page_regions;
if (isset($old_bgcolor)) {
$this->SetFillColorArray($old_bgcolor);
}
$this->x = $prev_x;
$this->y = $prev_y;
$this->lasth = $prev_lasth;
}
public function setLIsymbol($symbol='!') {
if (substr($symbol, 0, 4) == 'img|') {
$this->lisymbol = $symbol;
return;
}
$symbol = strtolower($symbol);
$valid_symbols = array('!', '#', 'disc', 'circle', 'square', '1', 'decimal', 'decimal-leading-zero', 'i', 'lower-roman', 'I', 'upper-roman', 'a', 'lower-alpha', 'lower-latin', 'A', 'upper-alpha', 'upper-latin', 'lower-greek');
if (in_array($symbol, $valid_symbols)) {
$this->lisymbol = $symbol;
} else {
$this->lisymbol = '';
}
}
public function SetBooklet($booklet=true, $inner=-1, $outer=-1) {
$this->booklet = $booklet;
if ($inner >= 0) {
$this->lMargin = $inner;
}
if ($outer >= 0) {
$this->rMargin = $outer;
}
}
protected function swapMargins($reverse=true) {
if ($reverse) {
$mtemp = $this->original_lMargin;
$this->original_lMargin = $this->original_rMargin;
$this->original_rMargin = $mtemp;
$deltam = $this->original_lMargin - $this->original_rMargin;
$this->lMargin += $deltam;
$this->rMargin -= $deltam;
}
}
public function setHtmlVSpace($tagvs) {
$this->tagvspaces = $tagvs;
}
public function setListIndentWidth($width) {
return $this->customlistindent = floatval($width);
}
public function setOpenCell($isopen) {
$this->opencell = $isopen;
}
public function setHtmlLinksStyle($color=array(0,0,255), $fontstyle='U') {
$this->htmlLinkColorArray = $color;
$this->htmlLinkFontStyle = $fontstyle;
}
public function getHTMLUnitToUnits($htmlval, $refsize=1, $defaultunit='px', $points=false) {
$supportedunits = array('%', 'em', 'ex', 'px', 'in', 'cm', 'mm', 'pc', 'pt');
$retval = 0;
$value = 0;
$unit = 'px';
if ($points) {
$k = 1;
} else {
$k = $this->k;
}
if (in_array($defaultunit, $supportedunits)) {
$unit = $defaultunit;
}
if (is_numeric($htmlval)) {
$value = floatval($htmlval);
} elseif (preg_match('/([0-9\.\-\+]+)/', $htmlval, $mnum)) {
$value = floatval($mnum[1]);
if (preg_match('/([a-z%]+)/', $htmlval, $munit)) {
if (in_array($munit[1], $supportedunits)) {
$unit = $munit[1];
}
}
}
switch ($unit) {
case '%': {
$retval = (($value * $refsize) / 100);
break;
}
case 'em': {
$retval = ($value * $refsize);
break;
}
case 'ex': {
$retval = ($value * ($refsize / 2));
break;
}
case 'in': {
$retval = (($value * $this->dpi) / $k);
break;
}
case 'cm': {
$retval = (($value / 2.54 * $this->dpi) / $k);
break;
}
case 'mm': {
$retval = (($value / 25.4 * $this->dpi) / $k);
break;
}
case 'pc': {
$retval = (($value * 12) / $k);
break;
}
case 'pt': {
$retval = ($value / $k);
break;
}
case 'px': {
$retval = $this->pixelsToUnits($value);
if ($points) {
$retval *= $this->k;
}
break;
}
}
return $retval;
}
protected function putHtmlListBullet($listdepth, $listtype='', $size=10) {
if ($this->state != 2) {
return;
}
$size /= $this->k;
$fill = '';
$bgcolor = $this->bgcolor;
$color = $this->fgcolor;
$strokecolor = $this->strokecolor;
$width = 0;
$textitem = '';
$tmpx = $this->x;
$lspace = $this->GetStringWidth(' ');
if ($listtype == '^') {
$this->lispacer = '';
return;
} elseif ($listtype == '!') {
$deftypes = array('disc', 'circle', 'square');
$listtype = $deftypes[($listdepth - 1) % 3];
} elseif ($listtype == '#') {
$listtype = 'decimal';
} elseif (substr($listtype, 0, 4) == 'img|') {
$img = explode('|', $listtype);
$listtype = 'img';
}
switch ($listtype) {
case 'none': {
break;
}
case 'disc': {
$r = $size / 6;
$lspace += (2 * $r);
if ($this->rtl) {
$this->x += $lspace;
} else {
$this->x -= $lspace;
}
$this->Circle(($this->x + $r), ($this->y + ($this->lasth / 2)), $r, 0, 360, 'F', array(), $color, 8);
break;
}
case 'circle': {
$r = $size / 6;
$lspace += (2 * $r);
if ($this->rtl) {
$this->x += $lspace;
} else {
$this->x -= $lspace;
}
$prev_line_style = $this->linestyleWidth.' '.$this->linestyleCap.' '.$this->linestyleJoin.' '.$this->linestyleDash.' '.$this->DrawColor;
$new_line_style = array('width' => ($r / 3), 'cap' => 'butt', 'join' => 'miter', 'dash' => 0, 'phase' => 0, 'color'=>$color);
$this->Circle(($this->x + $r), ($this->y + ($this->lasth / 2)), ($r * (1 - (1/6))), 0, 360, 'D', $new_line_style, array(), 8);
$this->_out($prev_line_style);
break;
}
case 'square': {
$l = $size / 3;
$lspace += $l;
if ($this->rtl) {;
$this->x += $lspace;
} else {
$this->x -= $lspace;
}
$this->Rect($this->x, ($this->y + (($this->lasth - $l) / 2)), $l, $l, 'F', array(), $color);
break;
}
case 'img': {
$lspace += $img[2];
if ($this->rtl) {;
$this->x += $lspace;
} else {
$this->x -= $lspace;
}
$imgtype = strtolower($img[1]);
$prev_y = $this->y;
switch ($imgtype) {
case 'svg': {
$this->ImageSVG($img[4], $this->x, ($this->y + (($this->lasth - $img[3]) / 2)), $img[2], $img[3], '', 'T', '', 0, false);
break;
}
case 'ai':
case 'eps': {
$this->ImageEps($img[4], $this->x, ($this->y + (($this->lasth - $img[3]) / 2)), $img[2], $img[3], '', true, 'T', '', 0, false);
break;
}
default: {
$this->Image($img[4], $this->x, ($this->y + (($this->lasth - $img[3]) / 2)), $img[2], $img[3], $img[1], '', 'T', false, 300, '', false, false, 0, false, false, false);
break;
}
}
$this->y = $prev_y;
break;
}
case '1':
case 'decimal': {
$textitem = $this->listcount[$this->listnum];
break;
}
case 'decimal-leading-zero': {
$textitem = sprintf('%02d', $this->listcount[$this->listnum]);
break;
}
case 'i':
case 'lower-roman': {
$textitem = strtolower(TCPDF_STATIC::intToRoman($this->listcount[$this->listnum]));
break;
}
case 'I':
case 'upper-roman': {
$textitem = TCPDF_STATIC::intToRoman($this->listcount[$this->listnum]);
break;
}
case 'a':
case 'lower-alpha':
case 'lower-latin': {
$textitem = chr(97 + $this->listcount[$this->listnum] - 1);
break;
}
case 'A':
case 'upper-alpha':
case 'upper-latin': {
$textitem = chr(65 + $this->listcount[$this->listnum] - 1);
break;
}
case 'lower-greek': {
$textitem = TCPDF_FONTS::unichr((945 + $this->listcount[$this->listnum] - 1), $this->isunicode);
break;
}
default: {
$textitem = $this->listcount[$this->listnum];
}
}
if (!TCPDF_STATIC::empty_string($textitem)) {
$prev_y = $this->y;
$h = $this->getCellHeight($this->FontSize);
if ($this->checkPageBreak($h) OR ($this->y < $prev_y)) {
$tmpx = $this->x;
}
if ($this->rtl) {
$textitem = '.'.$textitem;
} else {
$textitem = $textitem.'.';
}
$lspace += $this->GetStringWidth($textitem);
if ($this->rtl) {
$this->x += $lspace;
} else {
$this->x -= $lspace;
}
$this->Write($this->lasth, $textitem, '', false, '', false, 0, false);
}
$this->x = $tmpx;
$this->lispacer = '^';
$this->SetFillColorArray($bgcolor);
$this->SetDrawColorArray($strokecolor);
$this->SettextColorArray($color);
}
protected function getGraphicVars() {
$grapvars = array(
'FontFamily' => $this->FontFamily,
'FontStyle' => $this->FontStyle,
'FontSizePt' => $this->FontSizePt,
'rMargin' => $this->rMargin,
'lMargin' => $this->lMargin,
'cell_padding' => $this->cell_padding,
'cell_margin' => $this->cell_margin,
'LineWidth' => $this->LineWidth,
'linestyleWidth' => $this->linestyleWidth,
'linestyleCap' => $this->linestyleCap,
'linestyleJoin' => $this->linestyleJoin,
'linestyleDash' => $this->linestyleDash,
'textrendermode' => $this->textrendermode,
'textstrokewidth' => $this->textstrokewidth,
'DrawColor' => $this->DrawColor,
'FillColor' => $this->FillColor,
'TextColor' => $this->TextColor,
'ColorFlag' => $this->ColorFlag,
'bgcolor' => $this->bgcolor,
'fgcolor' => $this->fgcolor,
'htmlvspace' => $this->htmlvspace,
'listindent' => $this->listindent,
'listindentlevel' => $this->listindentlevel,
'listnum' => $this->listnum,
'listordered' => $this->listordered,
'listcount' => $this->listcount,
'lispacer' => $this->lispacer,
'cell_height_ratio' => $this->cell_height_ratio,
'font_stretching' => $this->font_stretching,
'font_spacing' => $this->font_spacing,
'alpha' => $this->alpha,
'lasth' => $this->lasth,
'tMargin' => $this->tMargin,
'bMargin' => $this->bMargin,
'AutoPageBreak' => $this->AutoPageBreak,
'PageBreakTrigger' => $this->PageBreakTrigger,
'x' => $this->x,
'y' => $this->y,
'w' => $this->w,
'h' => $this->h,
'wPt' => $this->wPt,
'hPt' => $this->hPt,
'fwPt' => $this->fwPt,
'fhPt' => $this->fhPt,
'page' => $this->page,
'current_column' => $this->current_column,
'num_columns' => $this->num_columns
);
return $grapvars;
}
protected function setGraphicVars($gvars, $extended=false) {
if ($this->state != 2) {
return;
}
$this->FontFamily = $gvars['FontFamily'];
$this->FontStyle = $gvars['FontStyle'];
$this->FontSizePt = $gvars['FontSizePt'];
$this->rMargin = $gvars['rMargin'];
$this->lMargin = $gvars['lMargin'];
$this->cell_padding = $gvars['cell_padding'];
$this->cell_margin = $gvars['cell_margin'];
$this->LineWidth = $gvars['LineWidth'];
$this->linestyleWidth = $gvars['linestyleWidth'];
$this->linestyleCap = $gvars['linestyleCap'];
$this->linestyleJoin = $gvars['linestyleJoin'];
$this->linestyleDash = $gvars['linestyleDash'];
$this->textrendermode = $gvars['textrendermode'];
$this->textstrokewidth = $gvars['textstrokewidth'];
$this->DrawColor = $gvars['DrawColor'];
$this->FillColor = $gvars['FillColor'];
$this->TextColor = $gvars['TextColor'];
$this->ColorFlag = $gvars['ColorFlag'];
$this->bgcolor = $gvars['bgcolor'];
$this->fgcolor = $gvars['fgcolor'];
$this->htmlvspace = $gvars['htmlvspace'];
$this->listindent = $gvars['listindent'];
$this->listindentlevel = $gvars['listindentlevel'];
$this->listnum = $gvars['listnum'];
$this->listordered = $gvars['listordered'];
$this->listcount = $gvars['listcount'];
$this->lispacer = $gvars['lispacer'];
$this->cell_height_ratio = $gvars['cell_height_ratio'];
$this->font_stretching = $gvars['font_stretching'];
$this->font_spacing = $gvars['font_spacing'];
$this->alpha = $gvars['alpha'];
if ($extended) {
$this->lasth = $gvars['lasth'];
$this->tMargin = $gvars['tMargin'];
$this->bMargin = $gvars['bMargin'];
$this->AutoPageBreak = $gvars['AutoPageBreak'];
$this->PageBreakTrigger = $gvars['PageBreakTrigger'];
$this->x = $gvars['x'];
$this->y = $gvars['y'];
$this->w = $gvars['w'];
$this->h = $gvars['h'];
$this->wPt = $gvars['wPt'];
$this->hPt = $gvars['hPt'];
$this->fwPt = $gvars['fwPt'];
$this->fhPt = $gvars['fhPt'];
$this->page = $gvars['page'];
$this->current_column = $gvars['current_column'];
$this->num_columns = $gvars['num_columns'];
}
$this->_out(''.$this->linestyleWidth.' '.$this->linestyleCap.' '.$this->linestyleJoin.' '.$this->linestyleDash.' '.$this->DrawColor.' '.$this->FillColor.'');
if (!TCPDF_STATIC::empty_string($this->FontFamily)) {
$this->SetFont($this->FontFamily, $this->FontStyle, $this->FontSizePt);
}
}
protected function _outSaveGraphicsState() {
$this->_out('q');
}
protected function _outRestoreGraphicsState() {
$this->_out('Q');
}
protected function setBuffer($data) {
$this->bufferlen += strlen($data);
$this->buffer .= $data;
}
protected function replaceBuffer($data) {
$this->bufferlen = strlen($data);
$this->buffer = $data;
}
protected function getBuffer() {
return $this->buffer;
}
protected function setPageBuffer($page, $data, $append=false) {
if ($append) {
$this->pages[$page] .= $data;
} else {
$this->pages[$page] = $data;
}
if ($append AND isset($this->pagelen[$page])) {
$this->pagelen[$page] += strlen($data);
} else {
$this->pagelen[$page] = strlen($data);
}
}
protected function getPageBuffer($page) {
if (isset($this->pages[$page])) {
return $this->pages[$page];
}
return false;
}
protected function setImageBuffer($image, $data) {
if (($data['i'] = array_search($image, $this->imagekeys)) === FALSE) {
$this->imagekeys[$this->numimages] = $image;
$data['i'] = $this->numimages;
++$this->numimages;
}
$this->images[$image] = $data;
return $data['i'];
}
protected function setImageSubBuffer($image, $key, $data) {
if (!isset($this->images[$image])) {
$this->setImageBuffer($image, array());
}
$this->images[$image][$key] = $data;
}
protected function getImageBuffer($image) {
if (isset($this->images[$image])) {
return $this->images[$image];
}
return false;
}
protected function setFontBuffer($font, $data) {
$this->fonts[$font] = $data;
if (!in_array($font, $this->fontkeys)) {
$this->fontkeys[] = $font;
++$this->n;
$this->font_obj_ids[$font] = $this->n;
$this->setFontSubBuffer($font, 'n', $this->n);
}
}
protected function setFontSubBuffer($font, $key, $data) {
if (!isset($this->fonts[$font])) {
$this->setFontBuffer($font, array());
}
$this->fonts[$font][$key] = $data;
}
protected function getFontBuffer($font) {
if (isset($this->fonts[$font])) {
return $this->fonts[$font];
}
return false;
}
public function movePage($frompage, $topage) {
if (($frompage > $this->numpages) OR ($frompage <= $topage)) {
return false;
}
if ($frompage == $this->page) {
$this->endPage();
}
$tmppage = $this->getPageBuffer($frompage);
$tmppagedim = $this->pagedim[$frompage];
$tmppagelen = $this->pagelen[$frompage];
$tmpintmrk = $this->intmrk[$frompage];
$tmpbordermrk = $this->bordermrk[$frompage];
$tmpcntmrk = $this->cntmrk[$frompage];
$tmppageobjects = $this->pageobjects[$frompage];
if (isset($this->footerpos[$frompage])) {
$tmpfooterpos = $this->footerpos[$frompage];
}
if (isset($this->footerlen[$frompage])) {
$tmpfooterlen = $this->footerlen[$frompage];
}
if (isset($this->transfmrk[$frompage])) {
$tmptransfmrk = $this->transfmrk[$frompage];
}
if (isset($this->PageAnnots[$frompage])) {
$tmpannots = $this->PageAnnots[$frompage];
}
if (isset($this->newpagegroup) AND !empty($this->newpagegroup)) {
for ($i = $frompage; $i > $topage; --$i) {
if (isset($this->newpagegroup[$i]) AND (($i + $this->pagegroups[$this->newpagegroup[$i]]) > $frompage)) {
--$this->pagegroups[$this->newpagegroup[$i]];
break;
}
}
for ($i = $topage; $i > 0; --$i) {
if (isset($this->newpagegroup[$i]) AND (($i + $this->pagegroups[$this->newpagegroup[$i]]) > $topage)) {
++$this->pagegroups[$this->newpagegroup[$i]];
break;
}
}
}
for ($i = $frompage; $i > $topage; --$i) {
$j = $i - 1;
$this->setPageBuffer($i, $this->getPageBuffer($j));
$this->pagedim[$i] = $this->pagedim[$j];
$this->pagelen[$i] = $this->pagelen[$j];
$this->intmrk[$i] = $this->intmrk[$j];
$this->bordermrk[$i] = $this->bordermrk[$j];
$this->cntmrk[$i] = $this->cntmrk[$j];
$this->pageobjects[$i] = $this->pageobjects[$j];
if (isset($this->footerpos[$j])) {
$this->footerpos[$i] = $this->footerpos[$j];
} elseif (isset($this->footerpos[$i])) {
unset($this->footerpos[$i]);
}
if (isset($this->footerlen[$j])) {
$this->footerlen[$i] = $this->footerlen[$j];
} elseif (isset($this->footerlen[$i])) {
unset($this->footerlen[$i]);
}
if (isset($this->transfmrk[$j])) {
$this->transfmrk[$i] = $this->transfmrk[$j];
} elseif (isset($this->transfmrk[$i])) {
unset($this->transfmrk[$i]);
}
if (isset($this->PageAnnots[$j])) {
$this->PageAnnots[$i] = $this->PageAnnots[$j];
} elseif (isset($this->PageAnnots[$i])) {
unset($this->PageAnnots[$i]);
}
if (isset($this->newpagegroup[$j])) {
$this->newpagegroup[$i] = $this->newpagegroup[$j];
unset($this->newpagegroup[$j]);
}
if ($this->currpagegroup == $j) {
$this->currpagegroup = $i;
}
}
$this->setPageBuffer($topage, $tmppage);
$this->pagedim[$topage] = $tmppagedim;
$this->pagelen[$topage] = $tmppagelen;
$this->intmrk[$topage] = $tmpintmrk;
$this->bordermrk[$topage] = $tmpbordermrk;
$this->cntmrk[$topage] = $tmpcntmrk;
$this->pageobjects[$topage] = $tmppageobjects;
if (isset($tmpfooterpos)) {
$this->footerpos[$topage] = $tmpfooterpos;
} elseif (isset($this->footerpos[$topage])) {
unset($this->footerpos[$topage]);
}
if (isset($tmpfooterlen)) {
$this->footerlen[$topage] = $tmpfooterlen;
} elseif (isset($this->footerlen[$topage])) {
unset($this->footerlen[$topage]);
}
if (isset($tmptransfmrk)) {
$this->transfmrk[$topage] = $tmptransfmrk;
} elseif (isset($this->transfmrk[$topage])) {
unset($this->transfmrk[$topage]);
}
if (isset($tmpannots)) {
$this->PageAnnots[$topage] = $tmpannots;
} elseif (isset($this->PageAnnots[$topage])) {
unset($this->PageAnnots[$topage]);
}
$tmpoutlines = $this->outlines;
foreach ($tmpoutlines as $key => $outline) {
if (!$outline['f']) {
if (($outline['p'] >= $topage) AND ($outline['p'] < $frompage)) {
$this->outlines[$key]['p'] = ($outline['p'] + 1);
} elseif ($outline['p'] == $frompage) {
$this->outlines[$key]['p'] = $topage;
}
}
}
$tmpdests = $this->dests;
foreach ($tmpdests as $key => $dest) {
if (!$dest['f']) {
if (($dest['p'] >= $topage) AND ($dest['p'] < $frompage)) {
$this->dests[$key]['p'] = ($dest['p'] + 1);
} elseif ($dest['p'] == $frompage) {
$this->dests[$key]['p'] = $topage;
}
}
}
$tmplinks = $this->links;
foreach ($tmplinks as $key => $link) {
if (!$link['f']) {
if (($link['p'] >= $topage) AND ($link['p'] < $frompage)) {
$this->links[$key]['p'] = ($link['p'] + 1);
} elseif ($link['p'] == $frompage) {
$this->links[$key]['p'] = $topage;
}
}
}
$jfrompage = $frompage;
$jtopage = $topage;
if (preg_match_all('/this\.addField\(\'([^\']*)\',\'([^\']*)\',([0-9]+)/', $this->javascript, $pamatch) > 0) {
foreach($pamatch[0] as $pk => $pmatch) {
$pagenum = intval($pamatch[3][$pk]) + 1;
if (($pagenum >= $jtopage) AND ($pagenum < $jfrompage)) {
$newpage = ($pagenum + 1);
} elseif ($pagenum == $jfrompage) {
$newpage = $jtopage;
} else {
$newpage = $pagenum;
}
--$newpage;
$newjs = "this.addField(\'".$pamatch[1][$pk]."\',\'".$pamatch[2][$pk]."\',".$newpage;
$this->javascript = str_replace($pmatch, $newjs, $this->javascript);
}
unset($pamatch);
}
$this->lastPage(true);
return true;
}
public function deletePage($page) {
if (($page < 1) OR ($page > $this->numpages)) {
return false;
}
unset($this->pages[$page]);
unset($this->pagedim[$page]);
unset($this->pagelen[$page]);
unset($this->intmrk[$page]);
unset($this->bordermrk[$page]);
unset($this->cntmrk[$page]);
foreach ($this->pageobjects[$page] as $oid) {
if (isset($this->offsets[$oid])){
unset($this->offsets[$oid]);
}
}
unset($this->pageobjects[$page]);
if (isset($this->footerpos[$page])) {
unset($this->footerpos[$page]);
}
if (isset($this->footerlen[$page])) {
unset($this->footerlen[$page]);
}
if (isset($this->transfmrk[$page])) {
unset($this->transfmrk[$page]);
}
if (isset($this->PageAnnots[$page])) {
unset($this->PageAnnots[$page]);
}
if (isset($this->newpagegroup) AND !empty($this->newpagegroup)) {
for ($i = $page; $i > 0; --$i) {
if (isset($this->newpagegroup[$i]) AND (($i + $this->pagegroups[$this->newpagegroup[$i]]) > $page)) {
--$this->pagegroups[$this->newpagegroup[$i]];
break;
}
}
}
if (isset($this->pageopen[$page])) {
unset($this->pageopen[$page]);
}
if ($page < $this->numpages) {
for ($i = $page; $i < $this->numpages; ++$i) {
$j = $i + 1;
$this->setPageBuffer($i, $this->getPageBuffer($j));
$this->pagedim[$i] = $this->pagedim[$j];
$this->pagelen[$i] = $this->pagelen[$j];
$this->intmrk[$i] = $this->intmrk[$j];
$this->bordermrk[$i] = $this->bordermrk[$j];
$this->cntmrk[$i] = $this->cntmrk[$j];
$this->pageobjects[$i] = $this->pageobjects[$j];
if (isset($this->footerpos[$j])) {
$this->footerpos[$i] = $this->footerpos[$j];
} elseif (isset($this->footerpos[$i])) {
unset($this->footerpos[$i]);
}
if (isset($this->footerlen[$j])) {
$this->footerlen[$i] = $this->footerlen[$j];
} elseif (isset($this->footerlen[$i])) {
unset($this->footerlen[$i]);
}
if (isset($this->transfmrk[$j])) {
$this->transfmrk[$i] = $this->transfmrk[$j];
} elseif (isset($this->transfmrk[$i])) {
unset($this->transfmrk[$i]);
}
if (isset($this->PageAnnots[$j])) {
$this->PageAnnots[$i] = $this->PageAnnots[$j];
} elseif (isset($this->PageAnnots[$i])) {
unset($this->PageAnnots[$i]);
}
if (isset($this->newpagegroup[$j])) {
$this->newpagegroup[$i] = $this->newpagegroup[$j];
unset($this->newpagegroup[$j]);
}
if ($this->currpagegroup == $j) {
$this->currpagegroup = $i;
}
if (isset($this->pageopen[$j])) {
$this->pageopen[$i] = $this->pageopen[$j];
} elseif (isset($this->pageopen[$i])) {
unset($this->pageopen[$i]);
}
}
unset($this->pages[$this->numpages]);
unset($this->pagedim[$this->numpages]);
unset($this->pagelen[$this->numpages]);
unset($this->intmrk[$this->numpages]);
unset($this->bordermrk[$this->numpages]);
unset($this->cntmrk[$this->numpages]);
foreach ($this->pageobjects[$this->numpages] as $oid) {
if (isset($this->offsets[$oid])){
unset($this->offsets[$oid]);
}
}
unset($this->pageobjects[$this->numpages]);
if (isset($this->footerpos[$this->numpages])) {
unset($this->footerpos[$this->numpages]);
}
if (isset($this->footerlen[$this->numpages])) {
unset($this->footerlen[$this->numpages]);
}
if (isset($this->transfmrk[$this->numpages])) {
unset($this->transfmrk[$this->numpages]);
}
if (isset($this->PageAnnots[$this->numpages])) {
unset($this->PageAnnots[$this->numpages]);
}
if (isset($this->newpagegroup[$this->numpages])) {
unset($this->newpagegroup[$this->numpages]);
}
if ($this->currpagegroup == $this->numpages) {
$this->currpagegroup = ($this->numpages - 1);
}
if (isset($this->pagegroups[$this->numpages])) {
unset($this->pagegroups[$this->numpages]);
}
if (isset($this->pageopen[$this->numpages])) {
unset($this->pageopen[$this->numpages]);
}
}
--$this->numpages;
$this->page = $this->numpages;
$tmpoutlines = $this->outlines;
foreach ($tmpoutlines as $key => $outline) {
if (!$outline['f']) {
if ($outline['p'] > $page) {
$this->outlines[$key]['p'] = $outline['p'] - 1;
} elseif ($outline['p'] == $page) {
unset($this->outlines[$key]);
}
}
}
$tmpdests = $this->dests;
foreach ($tmpdests as $key => $dest) {
if (!$dest['f']) {
if ($dest['p'] > $page) {
$this->dests[$key]['p'] = $dest['p'] - 1;
} elseif ($dest['p'] == $page) {
unset($this->dests[$key]);
}
}
}
$tmplinks = $this->links;
foreach ($tmplinks as $key => $link) {
if (!$link['f']) {
if ($link['p'] > $page) {
$this->links[$key]['p'] = $link['p'] - 1;
} elseif ($link['p'] == $page) {
unset($this->links[$key]);
}
}
}
$jpage = $page;
if (preg_match_all('/this\.addField\(\'([^\']*)\',\'([^\']*)\',([0-9]+)/', $this->javascript, $pamatch) > 0) {
foreach($pamatch[0] as $pk => $pmatch) {
$pagenum = intval($pamatch[3][$pk]) + 1;
if ($pagenum >= $jpage) {
$newpage = ($pagenum - 1);
} elseif ($pagenum == $jpage) {
$newpage = 1;
} else {
$newpage = $pagenum;
}
--$newpage;
$newjs = "this.addField(\'".$pamatch[1][$pk]."\',\'".$pamatch[2][$pk]."\',".$newpage;
$this->javascript = str_replace($pmatch, $newjs, $this->javascript);
}
unset($pamatch);
}
if ($this->numpages > 0) {
$this->lastPage(true);
}
return true;
}
public function copyPage($page=0) {
if ($page == 0) {
$page = $this->page;
}
if (($page < 1) OR ($page > $this->numpages)) {
return false;
}
$this->endPage();
++$this->numpages;
$this->page = $this->numpages;
$this->setPageBuffer($this->page, $this->getPageBuffer($page));
$this->pagedim[$this->page] = $this->pagedim[$page];
$this->pagelen[$this->page] = $this->pagelen[$page];
$this->intmrk[$this->page] = $this->intmrk[$page];
$this->bordermrk[$this->page] = $this->bordermrk[$page];
$this->cntmrk[$this->page] = $this->cntmrk[$page];
$this->pageobjects[$this->page] = $this->pageobjects[$page];
$this->pageopen[$this->page] = false;
if (isset($this->footerpos[$page])) {
$this->footerpos[$this->page] = $this->footerpos[$page];
}
if (isset($this->footerlen[$page])) {
$this->footerlen[$this->page] = $this->footerlen[$page];
}
if (isset($this->transfmrk[$page])) {
$this->transfmrk[$this->page] = $this->transfmrk[$page];
}
if (isset($this->PageAnnots[$page])) {
$this->PageAnnots[$this->page] = $this->PageAnnots[$page];
}
if (isset($this->newpagegroup[$page])) {
$this->newpagegroup[$this->page] = sizeof($this->newpagegroup) + 1;
$this->currpagegroup = $this->newpagegroup[$this->page];
$this->pagegroups[$this->currpagegroup] = 1;
} elseif (isset($this->currpagegroup) AND ($this->currpagegroup > 0)) {
++$this->pagegroups[$this->currpagegroup];
}
$tmpoutlines = $this->outlines;
foreach ($tmpoutlines as $key => $outline) {
if ($outline['p'] == $page) {
$this->outlines[] = array('t' => $outline['t'], 'l' => $outline['l'], 'x' => $outline['x'], 'y' => $outline['y'], 'p' => $this->page, 'f' => $outline['f'], 's' => $outline['s'], 'c' => $outline['c']);
}
}
$tmplinks = $this->links;
foreach ($tmplinks as $key => $link) {
if ($link['p'] == $page) {
$this->links[] = array('p' => $this->page, 'y' => $link['y'], 'f' => $link['f']);
}
}
$this->lastPage(true);
return true;
}
public function addTOC($page='', $numbersfont='', $filler='.', $toc_name='TOC', $style='', $color=array(0,0,0)) {
$fontsize = $this->FontSizePt;
$fontfamily = $this->FontFamily;
$fontstyle = $this->FontStyle;
$w = $this->w - $this->lMargin - $this->rMargin;
$spacer = $this->GetStringWidth(chr(32)) * 4;
$lmargin = $this->lMargin;
$rmargin = $this->rMargin;
$x_start = $this->GetX();
$page_first = $this->page;
$current_page = $this->page;
$page_fill_start = false;
$page_fill_end = false;
$current_column = $this->current_column;
if (TCPDF_STATIC::empty_string($numbersfont)) {
$numbersfont = $this->default_monospaced_font;
}
if (TCPDF_STATIC::empty_string($filler)) {
$filler = ' ';
}
if (TCPDF_STATIC::empty_string($page)) {
$gap = ' ';
} else {
$gap = '';
if ($page < 1) {
$page = 1;
}
}
$this->SetFont($numbersfont, $fontstyle, $fontsize);
$numwidth = $this->GetStringWidth('00000');
$maxpage = 0;
foreach ($this->outlines as $key => $outline) {
if (($this->page > $page_first) AND ($outline['p'] >= $this->numpages)) {
$outline['p'] += ($this->page - $page_first);
}
if ($this->rtl) {
$aligntext = 'R';
$alignnum = 'L';
} else {
$aligntext = 'L';
$alignnum = 'R';
}
if ($outline['l'] == 0) {
$this->SetFont($fontfamily, $outline['s'].'B', $fontsize);
} else {
$this->SetFont($fontfamily, $outline['s'], $fontsize - $outline['l']);
}
$this->SetTextColorArray($outline['c']);
$this->checkPageBreak(2 * $this->getCellHeight($this->FontSize));
if (($this->page == $current_page) AND ($this->current_column == $current_column)) {
$this->lMargin = $lmargin;
$this->rMargin = $rmargin;
} else {
if ($this->current_column != $current_column) {
if ($this->rtl) {
$x_start = $this->w - $this->columns[$this->current_column]['x'];
} else {
$x_start = $this->columns[$this->current_column]['x'];
}
}
$lmargin = $this->lMargin;
$rmargin = $this->rMargin;
$current_page = $this->page;
$current_column = $this->current_column;
}
$this->SetX($x_start);
$indent = ($spacer * $outline['l']);
if ($this->rtl) {
$this->x -= $indent;
$this->rMargin = $this->w - $this->x;
} else {
$this->x += $indent;
$this->lMargin = $this->x;
}
$link = $this->AddLink();
$this->SetLink($link, $outline['y'], $outline['p']);
if ($this->rtl) {
$txt = ' '.$outline['t'];
} else {
$txt = $outline['t'].' ';
}
$this->Write(0, $txt, $link, false, $aligntext, false, 0, false, false, 0, $numwidth, '');
if ($this->rtl) {
$tw = $this->x - $this->lMargin;
} else {
$tw = $this->w - $this->rMargin - $this->x;
}
$this->SetFont($numbersfont, $fontstyle, $fontsize);
if (TCPDF_STATIC::empty_string($page)) {
$pagenum = $outline['p'];
} else {
$pagenum = '{#'.($outline['p']).'}';
if ($this->isUnicodeFont()) {
$pagenum = '{'.$pagenum.'}';
}
$maxpage = max($maxpage, $outline['p']);
}
$fw = ($tw - $this->GetStringWidth($pagenum.$filler));
$wfiller = $this->GetStringWidth($filler);
if ($wfiller > 0) {
$numfills = floor($fw / $wfiller);
} else {
$numfills = 0;
}
if ($numfills > 0) {
$rowfill = str_repeat($filler, $numfills);
} else {
$rowfill = '';
}
if ($this->rtl) {
$pagenum = $pagenum.$gap.$rowfill;
} else {
$pagenum = $rowfill.$gap.$pagenum;
}
$this->Cell($tw, 0, $pagenum, 0, 1, $alignnum, 0, $link, 0);
}
$page_last = $this->getPage();
$numpages = ($page_last - $page_first + 1);
if ($this->booklet) {
$page_fill_start = ((($page_first % 2) == 0) XOR (($page % 2) == 0));
$page_fill_end = (!((($numpages % 2) == 0) XOR ($page_fill_start)));
if ($page_fill_start) {
$this->addPage();
++$page_last;
++$numpages;
}
if ($page_fill_end) {
$this->addPage();
++$page_last;
++$numpages;
}
}
$maxpage = max($maxpage, $page_last);
if (!TCPDF_STATIC::empty_string($page)) {
for ($p = $page_first; $p <= $page_last; ++$p) {
$temppage = $this->getPageBuffer($p);
for ($n = 1; $n <= $maxpage; ++$n) {
$a = '{#'.$n.'}';
$pnalias = $this->getInternalPageNumberAliases($a);
if (($n >= $page) AND ($n <= $this->numpages)) {
$np = $n + $numpages;
} else {
$np = $n;
}
$na = TCPDF_STATIC::formatTOCPageNumber(($this->starting_page_number + $np - 1));
$nu = TCPDF_FONTS::UTF8ToUTF16BE($na, false, $this->isunicode, $this->CurrentFont);
foreach ($pnalias['u'] as $u) {
$sfill = str_repeat($filler, max(0, (strlen($u) - strlen($nu.' '))));
if ($this->rtl) {
$nr = $nu.TCPDF_FONTS::UTF8ToUTF16BE(' '.$sfill, false, $this->isunicode, $this->CurrentFont);
} else {
$nr = TCPDF_FONTS::UTF8ToUTF16BE($sfill.' ', false, $this->isunicode, $this->CurrentFont).$nu;
}
$temppage = str_replace($u, $nr, $temppage);
}
foreach ($pnalias['a'] as $a) {
$sfill = str_repeat($filler, max(0, (strlen($a) - strlen($na.' '))));
if ($this->rtl) {
$nr = $na.' '.$sfill;
} else {
$nr = $sfill.' '.$na;
}
$temppage = str_replace($a, $nr, $temppage);
}
}
$this->setPageBuffer($p, $temppage);
}
$this->Bookmark($toc_name, 0, 0, $page_first, $style, $color);
if ($page_fill_start) {
$this->movePage($page_last, $page_first);
}
for ($i = 0; $i < $numpages; ++$i) {
$this->movePage($page_last, $page);
}
}
}
public function addHTMLTOC($page='', $toc_name='TOC', $templates=array(), $correct_align=true, $style='', $color=array(0,0,0)) {
$filler = ' ';
$prev_htmlLinkColorArray = $this->htmlLinkColorArray;
$prev_htmlLinkFontStyle = $this->htmlLinkFontStyle;
$this->htmlLinkColorArray = array();
$this->htmlLinkFontStyle = '';
$page_first = $this->getPage();
$page_fill_start = false;
$page_fill_end = false;
$current_font = $this->FontFamily;
foreach ($templates as $level => $html) {
$dom = $this->getHtmlDomArray($html);
foreach ($dom as $key => $value) {
if ($value['value'] == '#TOC_PAGE_NUMBER#') {
$this->SetFont($dom[($key - 1)]['fontname']);
$templates['F'.$level] = $this->isUnicodeFont();
}
}
}
$this->SetFont($current_font);
$maxpage = 0;
foreach ($this->outlines as $key => $outline) {
$row = $templates[$outline['l']];
if (TCPDF_STATIC::empty_string($page)) {
$pagenum = $outline['p'];
} else {
$pagenum = '{#'.($outline['p']).'}';
if (isset($templates['F'.$outline['l']]) && $templates['F'.$outline['l']]) {
$pagenum = '{'.$pagenum.'}';
}
$maxpage = max($maxpage, $outline['p']);
}
$row = str_replace('#TOC_DESCRIPTION#', $outline['t'], $row);
$row = str_replace('#TOC_PAGE_NUMBER#', $pagenum, $row);
$row = '<a href="#'.$outline['p'].','.$outline['y'].'">'.$row.'</a>';
$this->writeHTML($row, false, false, true, false, '');
}
$this->htmlLinkColorArray = $prev_htmlLinkColorArray;
$this->htmlLinkFontStyle = $prev_htmlLinkFontStyle;
$page_last = $this->getPage();
$numpages = ($page_last - $page_first + 1);
if ($this->booklet) {
$page_fill_start = ((($page_first % 2) == 0) XOR (($page % 2) == 0));
$page_fill_end = (!((($numpages % 2) == 0) XOR ($page_fill_start)));
if ($page_fill_start) {
$this->addPage();
++$page_last;
++$numpages;
}
if ($page_fill_end) {
$this->addPage();
++$page_last;
++$numpages;
}
}
$maxpage = max($maxpage, $page_last);
if (!TCPDF_STATIC::empty_string($page)) {
for ($p = $page_first; $p <= $page_last; ++$p) {
$temppage = $this->getPageBuffer($p);
for ($n = 1; $n <= $maxpage; ++$n) {
$a = '{#'.$n.'}';
$pnalias = $this->getInternalPageNumberAliases($a);
if ($n >= $page) {
$np = $n + $numpages;
} else {
$np = $n;
}
$na = TCPDF_STATIC::formatTOCPageNumber(($this->starting_page_number + $np - 1));
$nu = TCPDF_FONTS::UTF8ToUTF16BE($na, false, $this->isunicode, $this->CurrentFont);
foreach ($pnalias['u'] as $u) {
if ($correct_align) {
$sfill = str_repeat($filler, (strlen($u) - strlen($nu.' ')));
if ($this->rtl) {
$nr = $nu.TCPDF_FONTS::UTF8ToUTF16BE(' '.$sfill, false, $this->isunicode, $this->CurrentFont);
} else {
$nr = TCPDF_FONTS::UTF8ToUTF16BE($sfill.' ', false, $this->isunicode, $this->CurrentFont).$nu;
}
} else {
$nr = $nu;
}
$temppage = str_replace($u, $nr, $temppage);
}
foreach ($pnalias['a'] as $a) {
if ($correct_align) {
$sfill = str_repeat($filler, (strlen($a) - strlen($na.' ')));
if ($this->rtl) {
$nr = $na.' '.$sfill;
} else {
$nr = $sfill.' '.$na;
}
} else {
$nr = $na;
}
$temppage = str_replace($a, $nr, $temppage);
}
}
$this->setPageBuffer($p, $temppage);
}
$this->Bookmark($toc_name, 0, 0, $page_first, $style, $color);
if ($page_fill_start) {
$this->movePage($page_last, $page_first);
}
for ($i = 0; $i < $numpages; ++$i) {
$this->movePage($page_last, $page);
}
}
}
public function startTransaction() {
if (isset($this->objcopy)) {
$this->commitTransaction();
}
$this->start_transaction_page = $this->page;
$this->start_transaction_y = $this->y;
$this->objcopy = TCPDF_STATIC::objclone($this);
}
public function commitTransaction() {
if (isset($this->objcopy)) {
$this->objcopy->_destroy(true, true);
unset($this->objcopy);
}
}
public function rollbackTransaction($self=false) {
if (isset($this->objcopy)) {
$this->_destroy(true, true);
if ($self) {
$objvars = get_object_vars($this->objcopy);
foreach ($objvars as $key => $value) {
$this->$key = $value;
}
}
return $this->objcopy;
}
return $this;
}
public function setEqualColumns($numcols=0, $width=0, $y='') {
$this->columns = array();
if ($numcols < 2) {
$numcols = 0;
$this->columns = array();
} else {
$maxwidth = ($this->w - $this->original_lMargin - $this->original_rMargin) / $numcols;
if (($width == 0) OR ($width > $maxwidth)) {
$width = $maxwidth;
}
if (TCPDF_STATIC::empty_string($y)) {
$y = $this->y;
}
$space = (($this->w - $this->original_lMargin - $this->original_rMargin - ($numcols * $width)) / ($numcols - 1));
for ($i = 0; $i < $numcols; ++$i) {
$this->columns[$i] = array('w' => $width, 's' => $space, 'y' => $y);
}
}
$this->num_columns = $numcols;
$this->current_column = 0;
$this->column_start_page = $this->page;
$this->selectColumn(0);
}
public function resetColumns() {
$this->lMargin = $this->original_lMargin;
$this->rMargin = $this->original_rMargin;
$this->setEqualColumns();
}
public function setColumnsArray($columns) {
$this->columns = $columns;
$this->num_columns = count($columns);
$this->current_column = 0;
$this->column_start_page = $this->page;
$this->selectColumn(0);
}
public function selectColumn($col='') {
if (is_string($col)) {
$col = $this->current_column;
} elseif ($col >= $this->num_columns) {
$col = 0;
}
$xshift = array('x' => 0, 's' => array('H' => 0, 'V' => 0), 'p' => array('L' => 0, 'T' => 0, 'R' => 0, 'B' => 0));
$enable_thead = false;
if ($this->num_columns > 1) {
if ($col != $this->current_column) {
if ($this->column_start_page == $this->page) {
$this->y = $this->columns[$col]['y'];
} else {
$this->y = $this->tMargin;
}
if (($this->page > $this->maxselcol['page']) OR (($this->page == $this->maxselcol['page']) AND ($col > $this->maxselcol['column']))) {
$enable_thead = true;
$this->maxselcol['page'] = $this->page;
$this->maxselcol['column'] = $col;
}
}
$xshift = $this->colxshift;
$listindent = ($this->listindentlevel * $this->listindent);
$colpos = 0;
for ($i = 0; $i < $col; ++$i) {
$colpos += ($this->columns[$i]['w'] + $this->columns[$i]['s']);
}
if ($this->rtl) {
$x = $this->w - $this->original_rMargin - $colpos;
$this->rMargin = ($this->w - $x + $listindent);
$this->lMargin = ($x - $this->columns[$col]['w']);
$this->x = $x - $listindent;
} else {
$x = $this->original_lMargin + $colpos;
$this->lMargin = ($x + $listindent);
$this->rMargin = ($this->w - $x - $this->columns[$col]['w']);
$this->x = $x + $listindent;
}
$this->columns[$col]['x'] = $x;
}
$this->current_column = $col;
$this->newline = true;
if ((!TCPDF_STATIC::empty_string($this->thead)) AND (!$this->inthead)) {
if ($enable_thead) {
$this->writeHTML($this->thead, false, false, false, false, '');
$this->y += $xshift['s']['V'];
if (!isset($this->columns[$col]['th'])) {
$this->columns[$col]['th'] = array();
}
$this->columns[$col]['th']['\''.$this->page.'\''] = $this->y;
$this->lasth = 0;
} elseif (isset($this->columns[$col]['th']['\''.$this->page.'\''])) {
$this->y = $this->columns[$col]['th']['\''.$this->page.'\''];
}
}
if ($this->rtl) {
$this->rMargin += $xshift['x'];
$this->x -= ($xshift['x'] + $xshift['p']['R']);
} else {
$this->lMargin += $xshift['x'];
$this->x += $xshift['x'] + $xshift['p']['L'];
}
}
public function getColumn() {
return $this->current_column;
}
public function getNumberOfColumns() {
return $this->num_columns;
}
public function setTextRenderingMode($stroke=0, $fill=true, $clip=false) {
if ($stroke < 0) {
$stroke = 0;
}
if ($fill === true) {
if ($stroke > 0) {
if ($clip === true) {
$textrendermode = 6;
} else {
$textrendermode = 2;
}
$textstrokewidth = $stroke;
} else {
if ($clip === true) {
$textrendermode = 4;
} else {
$textrendermode = 0;
}
}
} else {
if ($stroke > 0) {
if ($clip === true) {
$textrendermode = 5;
} else {
$textrendermode = 1;
}
$textstrokewidth = $stroke;
} else {
if ($clip === true) {
$textrendermode = 7;
} else {
$textrendermode = 3;
}
}
}
$this->textrendermode = $textrendermode;
$this->textstrokewidth = $stroke;
}
public function setTextShadow($params=array('enabled'=>false, 'depth_w'=>0, 'depth_h'=>0, 'color'=>false, 'opacity'=>1, 'blend_mode'=>'Normal')) {
if (isset($params['enabled'])) {
$this->txtshadow['enabled'] = $params['enabled']?true:false;
} else {
$this->txtshadow['enabled'] = false;
}
if (isset($params['depth_w'])) {
$this->txtshadow['depth_w'] = floatval($params['depth_w']);
} else {
$this->txtshadow['depth_w'] = 0;
}
if (isset($params['depth_h'])) {
$this->txtshadow['depth_h'] = floatval($params['depth_h']);
} else {
$this->txtshadow['depth_h'] = 0;
}
if (isset($params['color']) AND ($params['color'] !== false) AND is_array($params['color'])) {
$this->txtshadow['color'] = $params['color'];
} else {
$this->txtshadow['color'] = $this->strokecolor;
}
if (isset($params['opacity'])) {
$this->txtshadow['opacity'] = min(1, max(0, floatval($params['opacity'])));
} else {
$this->txtshadow['opacity'] = 1;
}
if (isset($params['blend_mode']) AND in_array($params['blend_mode'], array('Normal', 'Multiply', 'Screen', 'Overlay', 'Darken', 'Lighten', 'ColorDodge', 'ColorBurn', 'HardLight', 'SoftLight', 'Difference', 'Exclusion', 'Hue', 'Saturation', 'Color', 'Luminosity'))) {
$this->txtshadow['blend_mode'] = $params['blend_mode'];
} else {
$this->txtshadow['blend_mode'] = 'Normal';
}
if ((($this->txtshadow['depth_w'] == 0) AND ($this->txtshadow['depth_h'] == 0)) OR ($this->txtshadow['opacity'] == 0)) {
$this->txtshadow['enabled'] = false;
}
}
public function getTextShadow() {
return $this->txtshadow;
}
protected function hyphenateWord($word, $patterns, $dictionary=array(), $leftmin=1, $rightmin=2, $charmin=1, $charmax=8) {
$hyphenword = array();
$numchars = count($word);
if ($numchars <= $charmin) {
return $word;
}
$word_string = TCPDF_FONTS::UTF8ArrSubString($word, '', '', $this->isunicode);
$pattern = '/^([a-zA-Z0-9_\.\-]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([a-zA-Z0-9\-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$/';
if (preg_match($pattern, $word_string) > 0) {
return $word;
}
$pattern = '/(([a-zA-Z0-9\-]+\.)?)((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([a-zA-Z0-9\-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$/';
if (preg_match($pattern, $word_string) > 0) {
return $word;
}
if (isset($dictionary[$word_string])) {
return TCPDF_FONTS::UTF8StringToArray($dictionary[$word_string], $this->isunicode, $this->CurrentFont);
}
$tmpword = array_merge(array(46), $word, array(46));
$tmpnumchars = $numchars + 2;
$maxpos = $tmpnumchars - 1;
for ($pos = 0; $pos < $maxpos; ++$pos) {
$imax = min(($tmpnumchars - $pos), $charmax);
for ($i = 1; $i <= $imax; ++$i) {
$subword = strtolower(TCPDF_FONTS::UTF8ArrSubString($tmpword, $pos, ($pos + $i), $this->isunicode));
if (isset($patterns[$subword])) {
$pattern = TCPDF_FONTS::UTF8StringToArray($patterns[$subword], $this->isunicode, $this->CurrentFont);
$pattern_length = count($pattern);
$digits = 1;
for ($j = 0; $j < $pattern_length; ++$j) {
if (($pattern[$j] >= 48) AND ($pattern[$j] <= 57)) {
if ($j == 0) {
$zero = $pos - 1;
} else {
$zero = $pos + $j - $digits;
}
$level = ($pattern[$j] - 48);
if (!isset($hyphenword[$zero]) OR ($hyphenword[$zero] < $level)) {
$hyphenword[$zero] = $level;
}
++$digits;
}
}
}
}
}
$inserted = 0;
$maxpos = $numchars - $rightmin;
for ($i = $leftmin; $i <= $maxpos; ++$i) {
if (isset($hyphenword[$i]) AND (($hyphenword[$i] % 2) != 0)) {
array_splice($word, $i + $inserted, 0, 173);
++$inserted;
}
}
return $word;
}
public function hyphenateText($text, $patterns, $dictionary=array(), $leftmin=1, $rightmin=2, $charmin=1, $charmax=8) {
$text = $this->unhtmlentities($text);
$word = array();
$txtarr = array();
$intag = false;
$skip = false;
if (!is_array($patterns)) {
$patterns = TCPDF_STATIC::getHyphenPatternsFromTEX($patterns);
}
$unichars = TCPDF_FONTS::UTF8StringToArray($text, $this->isunicode, $this->CurrentFont);
foreach ($unichars as $char) {
if ((!$intag) AND (!$skip) AND TCPDF_FONT_DATA::$uni_type[$char] == 'L') {
$word[] = $char;
} else {
if (!TCPDF_STATIC::empty_string($word)) {
$txtarr = array_merge($txtarr, $this->hyphenateWord($word, $patterns, $dictionary, $leftmin, $rightmin, $charmin, $charmax));
$word = array();
}
$txtarr[] = $char;
if (chr($char) == '<') {
$intag = true;
} elseif ($intag AND (chr($char) == '>')) {
$intag = false;
$expected = array(115, 116, 121, 108, 101);
$current = array_slice($txtarr, -6, 5);
$compare = array_diff($expected, $current);
if (empty($compare)) {
$expected = array(47);
$current = array_slice($txtarr, -7, 1);
$compare = array_diff($expected, $current);
if (empty($compare)) {
$skip = false;
} else {
$skip = true;
}
}
}
}
}
if (!TCPDF_STATIC::empty_string($word)) {
$txtarr = array_merge($txtarr, $this->hyphenateWord($word, $patterns, $dictionary, $leftmin, $rightmin, $charmin, $charmax));
}
return TCPDF_FONTS::UTF8ArrSubString($txtarr, '', '', $this->isunicode);
}
public function setRasterizeVectorImages($mode) {
$this->rasterize_vector_images = $mode;
}
public function setFontSubsetting($enable=true) {
if ($this->pdfa_mode) {
$this->font_subsetting = false;
} else {
$this->font_subsetting = $enable ? true : false;
}
}
public function getFontSubsetting() {
return $this->font_subsetting;
}
public function stringLeftTrim($str, $replace='') {
return preg_replace('/^'.$this->re_space['p'].'+/'.$this->re_space['m'], $replace, $str);
}
public function stringRightTrim($str, $replace='') {
return preg_replace('/'.$this->re_space['p'].'+$/'.$this->re_space['m'], $replace, $str);
}
public function stringTrim($str, $replace='') {
$str = $this->stringLeftTrim($str, $replace);
$str = $this->stringRightTrim($str, $replace);
return $str;
}
public function isUnicodeFont() {
return (($this->CurrentFont['type'] == 'TrueTypeUnicode') OR ($this->CurrentFont['type'] == 'cidfont0'));
}
public function getFontFamilyName($fontfamily) {
$fontfamily = preg_replace('/[^a-z0-9_\,]/', '', strtolower($fontfamily));
$fontslist = preg_split('/[,]/', $fontfamily);
foreach ($fontslist as $font) {
$font = preg_replace('/regular$/', '', $font);
$font = preg_replace('/italic$/', 'I', $font);
$font = preg_replace('/oblique$/', 'I', $font);
$font = preg_replace('/bold([I]?)$/', 'B\\1', $font);
$pattern = array();
$replacement = array();
$pattern[] = '/^serif|^cursive|^fantasy|^timesnewroman/';
$replacement[] = 'times';
$pattern[] = '/^sansserif/';
$replacement[] = 'helvetica';
$pattern[] = '/^monospace/';
$replacement[] = 'courier';
$font = preg_replace($pattern, $replacement, $font);
if (in_array(strtolower($font), $this->fontlist) OR in_array($font, $this->fontkeys)) {
return $font;
}
}
return $this->CurrentFont['fontkey'];
}
public function startTemplate($w=0, $h=0, $group=false) {
if ($this->inxobj) {
return false;
}
$this->inxobj = true;
++$this->n;
$this->xobjid = 'XT'.$this->n;
$this->xobjects[$this->xobjid] = array('n' => $this->n);
$this->xobjects[$this->xobjid]['gvars'] = $this->getGraphicVars();
$this->xobjects[$this->xobjid]['intmrk'] = 0;
$this->xobjects[$this->xobjid]['transfmrk'] = array();
$this->xobjects[$this->xobjid]['outdata'] = '';
$this->xobjects[$this->xobjid]['xobjects'] = array();
$this->xobjects[$this->xobjid]['images'] = array();
$this->xobjects[$this->xobjid]['fonts'] = array();
$this->xobjects[$this->xobjid]['annotations'] = array();
$this->xobjects[$this->xobjid]['extgstates'] = array();
$this->xobjects[$this->xobjid]['gradients'] = array();
$this->xobjects[$this->xobjid]['spot_colors'] = array();
$this->num_columns = 1;
$this->current_column = 0;
$this->SetAutoPageBreak(false);
if (($w === '') OR ($w <= 0)) {
$w = $this->w - $this->lMargin - $this->rMargin;
}
if (($h === '') OR ($h <= 0)) {
$h = $this->h - $this->tMargin - $this->bMargin;
}
$this->xobjects[$this->xobjid]['x'] = 0;
$this->xobjects[$this->xobjid]['y'] = 0;
$this->xobjects[$this->xobjid]['w'] = $w;
$this->xobjects[$this->xobjid]['h'] = $h;
$this->w = $w;
$this->h = $h;
$this->wPt = $this->w * $this->k;
$this->hPt = $this->h * $this->k;
$this->fwPt = $this->wPt;
$this->fhPt = $this->hPt;
$this->x = 0;
$this->y = 0;
$this->lMargin = 0;
$this->rMargin = 0;
$this->tMargin = 0;
$this->bMargin = 0;
$this->xobjects[$this->xobjid]['group'] = $group;
return $this->xobjid;
}
public function endTemplate() {
if (!$this->inxobj) {
return false;
}
$this->inxobj = false;
$this->setGraphicVars($this->xobjects[$this->xobjid]['gvars'], true);
return $this->xobjid;
}
public function printTemplate($id, $x='', $y='', $w=0, $h=0, $align='', $palign='', $fitonpage=false) {
if ($this->state != 2) {
return;
}
if (!isset($this->xobjects[$id])) {
$this->Error('The XObject Template \''.$id.'\' doesn\'t exist!');
}
if ($this->inxobj) {
if ($id == $this->xobjid) {
$this->endTemplate();
} else {
$this->xobjects[$this->xobjid]['xobjects'][$id] = $this->xobjects[$id];
}
}
if ($x === '') {
$x = $this->x;
}
if ($y === '') {
$y = $this->y;
}
list($x, $y) = $this->checkPageRegions($h, $x, $y);
$ow = $this->xobjects[$id]['w'];
if ($ow <= 0) {
$ow = 1;
}
$oh = $this->xobjects[$id]['h'];
if ($oh <= 0) {
$oh = 1;
}
if (($w <= 0) AND ($h <= 0)) {
$w = $ow;
$h = $oh;
} elseif ($w <= 0) {
$w = $h * $ow / $oh;
} elseif ($h <= 0) {
$h = $w * $oh / $ow;
}
list($w, $h, $x, $y) = $this->fitBlock($w, $h, $x, $y, $fitonpage);
$rb_y = $y + $h;
if ($this->rtl) {
if ($palign == 'L') {
$xt = $this->lMargin;
} elseif ($palign == 'C') {
$xt = ($this->w + $this->lMargin - $this->rMargin - $w) / 2;
} elseif ($palign == 'R') {
$xt = $this->w - $this->rMargin - $w;
} else {
$xt = $x - $w;
}
$rb_x = $xt;
} else {
if ($palign == 'L') {
$xt = $this->lMargin;
} elseif ($palign == 'C') {
$xt = ($this->w + $this->lMargin - $this->rMargin - $w) / 2;
} elseif ($palign == 'R') {
$xt = $this->w - $this->rMargin - $w;
} else {
$xt = $x;
}
$rb_x = $xt + $w;
}
$this->StartTransform();
$sx = ($w / $ow);
$sy = ($h / $oh);
$tm = array();
$tm[0] = $sx;
$tm[1] = 0;
$tm[2] = 0;
$tm[3] = $sy;
$tm[4] = $xt * $this->k;
$tm[5] = ($this->h - $h - $y) * $this->k;
$this->Transform($tm);
$this->_out('/'.$id.' Do');
$this->StopTransform();
if (!empty($this->xobjects[$id]['annotations'])) {
foreach ($this->xobjects[$id]['annotations'] as $annot) {
$coordlt = TCPDF_STATIC::getTransformationMatrixProduct($tm, array(1, 0, 0, 1, ($annot['x'] * $this->k), (-$annot['y'] * $this->k)));
$ax = ($coordlt[4] / $this->k);
$ay = ($this->h - $h - ($coordlt[5] / $this->k));
$coordrb = TCPDF_STATIC::getTransformationMatrixProduct($tm, array(1, 0, 0, 1, (($annot['x'] + $annot['w']) * $this->k), ((-$annot['y'] - $annot['h']) * $this->k)));
$aw = ($coordrb[4] / $this->k) - $ax;
$ah = ($this->h - $h - ($coordrb[5] / $this->k)) - $ay;
$this->Annotation($ax, $ay, $aw, $ah, $annot['text'], $annot['opt'], $annot['spaces']);
}
}
switch($align) {
case 'T': {
$this->y = $y;
$this->x = $rb_x;
break;
}
case 'M': {
$this->y = $y + round($h/2);
$this->x = $rb_x;
break;
}
case 'B': {
$this->y = $rb_y;
$this->x = $rb_x;
break;
}
case 'N': {
$this->SetY($rb_y);
break;
}
default:{
break;
}
}
}
public function setFontStretching($perc=100) {
$this->font_stretching = $perc;
}
public function getFontStretching() {
return $this->font_stretching;
}
public function setFontSpacing($spacing=0) {
$this->font_spacing = $spacing;
}
public function getFontSpacing() {
return $this->font_spacing;
}
public function getPageRegions() {
return $this->page_regions;
}
public function setPageRegions($regions=array()) {
$this->page_regions = array();
foreach ($regions as $data) {
$this->addPageRegion($data);
}
}
public function addPageRegion($region) {
if (!isset($region['page']) OR empty($region['page'])) {
$region['page'] = $this->page;
}
if (isset($region['xt']) AND isset($region['xb']) AND ($region['xt'] > 0) AND ($region['xb'] > 0)
AND isset($region['yt']) AND isset($region['yb']) AND ($region['yt'] >= 0) AND ($region['yt'] < $region['yb'])
AND isset($region['side']) AND (($region['side'] == 'L') OR ($region['side'] == 'R'))) {
$this->page_regions[] = $region;
}
}
public function removePageRegion($key) {
if (isset($this->page_regions[$key])) {
unset($this->page_regions[$key]);
}
}
protected function checkPageRegions($h, $x, $y) {
if ($x === '') {
$x = $this->x;
}
if ($y === '') {
$y = $this->y;
}
if (!$this->check_page_regions OR empty($this->page_regions)) {
return array($x, $y);
}
if (empty($h)) {
$h = $this->getCellHeight($this->FontSize);
}
if ($this->checkPageBreak($h, $y)) {
$x = $this->x;
$y = $this->y;
}
if ($this->num_columns > 1) {
if ($this->rtl) {
$this->lMargin = ($this->columns[$this->current_column]['x'] - $this->columns[$this->current_column]['w']);
} else {
$this->rMargin = ($this->w - $this->columns[$this->current_column]['x'] - $this->columns[$this->current_column]['w']);
}
} else {
if ($this->rtl) {
$this->lMargin = max($this->clMargin, $this->original_lMargin);
} else {
$this->rMargin = max($this->crMargin, $this->original_rMargin);
}
}
foreach ($this->page_regions as $regid => $regdata) {
if ($regdata['page'] == $this->page) {
if (($y > ($regdata['yt'] - $h)) AND ($y <= $regdata['yb'])) {
$minv = ($regdata['xb'] - $regdata['xt']) / ($regdata['yb'] - $regdata['yt']);
$yt = max($y, $regdata['yt']);
$yb = min(($yt + $h), $regdata['yb']);
$xt = (($yt - $regdata['yt']) * $minv) + $regdata['xt'];
$xb = (($yb - $regdata['yt']) * $minv) + $regdata['xt'];
if ($regdata['side'] == 'L') {
$new_margin = max($xt, $xb);
if ($this->lMargin < $new_margin) {
if ($this->rtl) {
$this->lMargin = max(0, $new_margin);
}
if ($x < $new_margin) {
$x = $new_margin;
if ($new_margin > ($this->w - $this->rMargin)) {
$y = $regdata['yb'] - $h;
}
}
}
} elseif ($regdata['side'] == 'R') {
$new_margin = min($xt, $xb);
if (($this->w - $this->rMargin) > $new_margin) {
if (!$this->rtl) {
$this->rMargin = max(0, ($this->w - $new_margin));
}
if ($x > $new_margin) {
$x = $new_margin;
if ($new_margin > $this->lMargin) {
$y = $regdata['yb'] - $h;
}
}
}
}
}
}
}
return array($x, $y);
}
public function ImageSVG($file, $x='', $y='', $w=0, $h=0, $link='', $align='', $palign='', $border=0, $fitonpage=false) {
if ($this->state != 2) {
return;
}
$this->svggradients = array();
$this->svggradientid = 0;
$this->svgdefsmode = false;
$this->svgdefs = array();
$this->svgclipmode = false;
$this->svgclippaths = array();
$this->svgcliptm = array();
$this->svgclipid = 0;
$this->svgtext = '';
$this->svgtextmode = array();
if ($this->rasterize_vector_images AND ($w > 0) AND ($h > 0)) {
return $this->Image($file, $x, $y, $w, $h, 'SVG', $link, $align, true, 300, $palign, false, false, $border, false, false, false);
}
if ($file[0] === '@') {
$this->svgdir = '';
$svgdata = substr($file, 1);
} else {
$this->svgdir = dirname($file);
$svgdata = TCPDF_STATIC::fileGetContents($file);
}
if ($svgdata === FALSE) {
$this->Error('SVG file not found: '.$file);
}
if ($x === '') {
$x = $this->x;
}
if ($y === '') {
$y = $this->y;
}
list($x, $y) = $this->checkPageRegions($h, $x, $y);
$k = $this->k;
$ox = 0;
$oy = 0;
$ow = $w;
$oh = $h;
$aspect_ratio_align = 'xMidYMid';
$aspect_ratio_ms = 'meet';
$regs = array();
preg_match('/<svg([^\>]*)>/si', $svgdata, $regs);
if (isset($regs[1]) AND !empty($regs[1])) {
$tmp = array();
if (preg_match('/[\s]+x[\s]*=[\s]*"([^"]*)"/si', $regs[1], $tmp)) {
$ox = $this->getHTMLUnitToUnits($tmp[1], 0, $this->svgunit, false);
}
$tmp = array();
if (preg_match('/[\s]+y[\s]*=[\s]*"([^"]*)"/si', $regs[1], $tmp)) {
$oy = $this->getHTMLUnitToUnits($tmp[1], 0, $this->svgunit, false);
}
$tmp = array();
if (preg_match('/[\s]+width[\s]*=[\s]*"([^"]*)"/si', $regs[1], $tmp)) {
$ow = $this->getHTMLUnitToUnits($tmp[1], 1, $this->svgunit, false);
}
$tmp = array();
if (preg_match('/[\s]+height[\s]*=[\s]*"([^"]*)"/si', $regs[1], $tmp)) {
$oh = $this->getHTMLUnitToUnits($tmp[1], 1, $this->svgunit, false);
}
$tmp = array();
$view_box = array();
if (preg_match('/[\s]+viewBox[\s]*=[\s]*"[\s]*([0-9\.\-]+)[\s]+([0-9\.\-]+)[\s]+([0-9\.]+)[\s]+([0-9\.]+)[\s]*"/si', $regs[1], $tmp)) {
if (count($tmp) == 5) {
array_shift($tmp);
foreach ($tmp as $key => $val) {
$view_box[$key] = $this->getHTMLUnitToUnits($val, 0, $this->svgunit, false);
}
$ox = $view_box[0];
$oy = $view_box[1];
}
$tmp = array();
if (preg_match('/[\s]+preserveAspectRatio[\s]*=[\s]*"([^"]*)"/si', $regs[1], $tmp)) {
$aspect_ratio = preg_split('/[\s]+/si', $tmp[1]);
switch (count($aspect_ratio)) {
case 3: {
$aspect_ratio_align = $aspect_ratio[1];
$aspect_ratio_ms = $aspect_ratio[2];
break;
}
case 2: {
$aspect_ratio_align = $aspect_ratio[0];
$aspect_ratio_ms = $aspect_ratio[1];
break;
}
case 1: {
$aspect_ratio_align = $aspect_ratio[0];
$aspect_ratio_ms = 'meet';
break;
}
}
}
}
}
if ($ow <= 0) {
$ow = 1;
}
if ($oh <= 0) {
$oh = 1;
}
if (($w <= 0) AND ($h <= 0)) {
$w = $ow;
$h = $oh;
} elseif ($w <= 0) {
$w = $h * $ow / $oh;
} elseif ($h <= 0) {
$h = $w * $oh / $ow;
}
list($w, $h, $x, $y) = $this->fitBlock($w, $h, $x, $y, $fitonpage);
if ($this->rasterize_vector_images) {
return $this->Image($file, $x, $y, $w, $h, 'SVG', $link, $align, true, 300, $palign, false, false, $border, false, false, false);
}
$this->img_rb_y = $y + $h;
if ($this->rtl) {
if ($palign == 'L') {
$ximg = $this->lMargin;
} elseif ($palign == 'C') {
$ximg = ($this->w + $this->lMargin - $this->rMargin - $w) / 2;
} elseif ($palign == 'R') {
$ximg = $this->w - $this->rMargin - $w;
} else {
$ximg = $x - $w;
}
$this->img_rb_x = $ximg;
} else {
if ($palign == 'L') {
$ximg = $this->lMargin;
} elseif ($palign == 'C') {
$ximg = ($this->w + $this->lMargin - $this->rMargin - $w) / 2;
} elseif ($palign == 'R') {
$ximg = $this->w - $this->rMargin - $w;
} else {
$ximg = $x;
}
$this->img_rb_x = $ximg + $w;
}
$gvars = $this->getGraphicVars();
$svgoffset_x = ($ximg - $ox) * $this->k;
$svgoffset_y = -($y - $oy) * $this->k;
if (isset($view_box[2]) AND ($view_box[2] > 0) AND ($view_box[3] > 0)) {
$ow = $view_box[2];
$oh = $view_box[3];
} else {
if ($ow <= 0) {
$ow = $w;
}
if ($oh <= 0) {
$oh = $h;
}
}
$svgscale_x = $w / $ow;
$svgscale_y = $h / $oh;
if ($aspect_ratio_align != 'none') {
$svgscale_old_x = $svgscale_x;
$svgscale_old_y = $svgscale_y;
if ($aspect_ratio_ms == 'slice') {
if ($svgscale_x > $svgscale_y) {
$svgscale_y = $svgscale_x;
} elseif ($svgscale_x < $svgscale_y) {
$svgscale_x = $svgscale_y;
}
} else {
if ($svgscale_x < $svgscale_y) {
$svgscale_y = $svgscale_x;
} elseif ($svgscale_x > $svgscale_y) {
$svgscale_x = $svgscale_y;
}
}
switch (substr($aspect_ratio_align, 1, 3)) {
case 'Min': {
break;
}
case 'Max': {
$svgoffset_x += (($w * $this->k) - ($ow * $this->k * $svgscale_x));
break;
}
default:
case 'Mid': {
$svgoffset_x += ((($w * $this->k) - ($ow * $this->k * $svgscale_x)) / 2);
break;
}
}
switch (substr($aspect_ratio_align, 5)) {
case 'Min': {
break;
}
case 'Max': {
$svgoffset_y -= (($h * $this->k) - ($oh * $this->k * $svgscale_y));
break;
}
default:
case 'Mid': {
$svgoffset_y -= ((($h * $this->k) - ($oh * $this->k * $svgscale_y)) / 2);
break;
}
}
}
$page_break_mode = $this->AutoPageBreak;
$page_break_margin = $this->getBreakMargin();
$cell_padding = $this->cell_padding;
$this->SetCellPadding(0);
$this->SetAutoPageBreak(false);
$this->_out('q'.$this->epsmarker);
$this->Rect($ximg, $y, $w, $h, 'CNZ', array(), array());
$e = $ox * $this->k * (1 - $svgscale_x);
$f = ($this->h - $oy) * $this->k * (1 - $svgscale_y);
$this->_out(sprintf('%F %F %F %F %F %F cm', $svgscale_x, 0, 0, $svgscale_y, ($e + $svgoffset_x), ($f + $svgoffset_y)));
$this->parser = xml_parser_create('UTF-8');
xml_set_object($this->parser, $this);
xml_parser_set_option($this->parser, XML_OPTION_CASE_FOLDING, 0);
xml_set_element_handler($this->parser, 'startSVGElementHandler', 'endSVGElementHandler');
xml_set_character_data_handler($this->parser, 'segSVGContentHandler');
if (!xml_parse($this->parser, $svgdata)) {
$error_message = sprintf('SVG Error: %s at line %d', xml_error_string(xml_get_error_code($this->parser)), xml_get_current_line_number($this->parser));
$this->Error($error_message);
}
xml_parser_free($this->parser);
$this->_out($this->epsmarker.'Q');
$this->setGraphicVars($gvars);
$this->lasth = $gvars['lasth'];
if (!empty($border)) {
$bx = $this->x;
$by = $this->y;
$this->x = $ximg;
if ($this->rtl) {
$this->x += $w;
}
$this->y = $y;
$this->Cell($w, $h, '', $border, 0, '', 0, '', 0, true);
$this->x = $bx;
$this->y = $by;
}
if ($link) {
$this->Link($ximg, $y, $w, $h, $link, 0);
}
switch($align) {
case 'T':{
$this->y = $y;
$this->x = $this->img_rb_x;
break;
}
case 'M':{
$this->y = $y + round($h/2);
$this->x = $this->img_rb_x;
break;
}
case 'B':{
$this->y = $this->img_rb_y;
$this->x = $this->img_rb_x;
break;
}
case 'N':{
$this->SetY($this->img_rb_y);
break;
}
default:{
$this->x = $gvars['x'];
$this->y = $gvars['y'];
$this->page = $gvars['page'];
$this->current_column = $gvars['current_column'];
$this->tMargin = $gvars['tMargin'];
$this->bMargin = $gvars['bMargin'];
$this->w = $gvars['w'];
$this->h = $gvars['h'];
$this->wPt = $gvars['wPt'];
$this->hPt = $gvars['hPt'];
$this->fwPt = $gvars['fwPt'];
$this->fhPt = $gvars['fhPt'];
break;
}
}
$this->endlinex = $this->img_rb_x;
$this->SetAutoPageBreak($page_break_mode, $page_break_margin);
$this->cell_padding = $cell_padding;
}
protected function convertSVGtMatrix($tm) {
$a = $tm[0];
$b = -$tm[1];
$c = -$tm[2];
$d = $tm[3];
$e = $this->getHTMLUnitToUnits($tm[4], 1, $this->svgunit, false) * $this->k;
$f = -$this->getHTMLUnitToUnits($tm[5], 1, $this->svgunit, false) * $this->k;
$x = 0;
$y = $this->h * $this->k;
$e = ($x * (1 - $a)) - ($y * $c) + $e;
$f = ($y * (1 - $d)) - ($x * $b) + $f;
return array($a, $b, $c, $d, $e, $f);
}
protected function SVGTransform($tm) {
$this->Transform($this->convertSVGtMatrix($tm));
}
protected function setSVGStyles($svgstyle, $prevsvgstyle, $x=0, $y=0, $w=1, $h=1, $clip_function='', $clip_params=array()) {
if ($this->state != 2) {
return;
}
$objstyle = '';
$minlen = (0.01 / $this->k);
if (!isset($svgstyle['opacity'])) {
return $objstyle;
}
$regs = array();
if (preg_match('/url\([\s]*\#([^\)]*)\)/si', $svgstyle['clip-path'], $regs)) {
$clip_path = $this->svgclippaths[$regs[1]];
foreach ($clip_path as $cp) {
$this->startSVGElementHandler('clip-path', $cp['name'], $cp['attribs'], $cp['tm']);
}
}
if ($svgstyle['opacity'] != 1) {
$this->setAlpha($svgstyle['opacity'], 'Normal', $svgstyle['opacity'], false);
}
$fill_color = TCPDF_COLORS::convertHTMLColorToDec($svgstyle['color'], $this->spot_colors);
$this->SetFillColorArray($fill_color);
$text_color = TCPDF_COLORS::convertHTMLColorToDec($svgstyle['text-color'], $this->spot_colors);
$this->SetTextColorArray($text_color);
if (preg_match('/rect\(([a-z0-9\-\.]*)[\s]*([a-z0-9\-\.]*)[\s]*([a-z0-9\-\.]*)[\s]*([a-z0-9\-\.]*)\)/si', $svgstyle['clip'], $regs)) {
$top = (isset($regs[1])?$this->getHTMLUnitToUnits($regs[1], 0, $this->svgunit, false):0);
$right = (isset($regs[2])?$this->getHTMLUnitToUnits($regs[2], 0, $this->svgunit, false):0);
$bottom = (isset($regs[3])?$this->getHTMLUnitToUnits($regs[3], 0, $this->svgunit, false):0);
$left = (isset($regs[4])?$this->getHTMLUnitToUnits($regs[4], 0, $this->svgunit, false):0);
$cx = $x + $left;
$cy = $y + $top;
$cw = $w - $left - $right;
$ch = $h - $top - $bottom;
if ($svgstyle['clip-rule'] == 'evenodd') {
$clip_rule = 'CNZ';
} else {
$clip_rule = 'CEO';
}
$this->Rect($cx, $cy, $cw, $ch, $clip_rule, array(), array());
}
$regs = array();
if (preg_match('/url\([\s]*\#([^\)]*)\)/si', $svgstyle['fill'], $regs)) {
$gradient = $this->svggradients[$regs[1]];
if (isset($gradient['xref'])) {
$newgradient = $this->svggradients[$gradient['xref']];
$newgradient['coords'] = $gradient['coords'];
$newgradient['mode'] = $gradient['mode'];
$newgradient['type'] = $gradient['type'];
$newgradient['gradientUnits'] = $gradient['gradientUnits'];
if (isset($gradient['gradientTransform'])) {
$newgradient['gradientTransform'] = $gradient['gradientTransform'];
}
$gradient = $newgradient;
}
$this->_outSaveGraphicsState();
if (!empty($clip_function) AND method_exists($this, $clip_function)) {
$bbox = call_user_func_array(array($this, $clip_function), $clip_params);
if ((!isset($gradient['type']) OR ($gradient['type'] != 3)) AND is_array($bbox) AND (count($bbox) == 4)) {
list($x, $y, $w, $h) = $bbox;
}
}
if ($gradient['mode'] == 'measure') {
if (!isset($gradient['coords'][4])) {
$gradient['coords'][4] = 0.5;
}
if (isset($gradient['gradientTransform']) AND !empty($gradient['gradientTransform'])) {
$gtm = $gradient['gradientTransform'];
$xa = ($gtm[0] * $gradient['coords'][0]) + ($gtm[2] * $gradient['coords'][1]) + $gtm[4];
$ya = ($gtm[1] * $gradient['coords'][0]) + ($gtm[3] * $gradient['coords'][1]) + $gtm[5];
$xb = ($gtm[0] * $gradient['coords'][2]) + ($gtm[2] * $gradient['coords'][3]) + $gtm[4];
$yb = ($gtm[1] * $gradient['coords'][2]) + ($gtm[3] * $gradient['coords'][3]) + $gtm[5];
$r = sqrt(pow(($gtm[0] * $gradient['coords'][4]), 2) + pow(($gtm[1] * $gradient['coords'][4]), 2));
$gradient['coords'][0] = $xa;
$gradient['coords'][1] = $ya;
$gradient['coords'][2] = $xb;
$gradient['coords'][3] = $yb;
$gradient['coords'][4] = $r;
}
$gradient['coords'][0] = $this->getHTMLUnitToUnits($gradient['coords'][0], 0, $this->svgunit, false);
$gradient['coords'][1] = $this->getHTMLUnitToUnits($gradient['coords'][1], 0, $this->svgunit, false);
$gradient['coords'][2] = $this->getHTMLUnitToUnits($gradient['coords'][2], 0, $this->svgunit, false);
$gradient['coords'][3] = $this->getHTMLUnitToUnits($gradient['coords'][3], 0, $this->svgunit, false);
$gradient['coords'][4] = $this->getHTMLUnitToUnits($gradient['coords'][4], 0, $this->svgunit, false);
if ($w <= $minlen) {
$w = $minlen;
}
if ($h <= $minlen) {
$h = $minlen;
}
if ($gradient['gradientUnits'] == 'objectBoundingBox') {
$gradient['coords'][0] += $x;
$gradient['coords'][1] += $y;
$gradient['coords'][2] += $x;
$gradient['coords'][3] += $y;
}
$gradient['coords'][0] = (($gradient['coords'][0] - $x) / $w);
$gradient['coords'][1] = (($gradient['coords'][1] - $y) / $h);
$gradient['coords'][2] = (($gradient['coords'][2] - $x) / $w);
$gradient['coords'][3] = (($gradient['coords'][3] - $y) / $h);
$gradient['coords'][4] /= $w;
} elseif ($gradient['mode'] == 'percentage') {
foreach($gradient['coords'] as $key => $val) {
$gradient['coords'][$key] = (intval($val) / 100);
if ($val < 0) {
$gradient['coords'][$key] = 0;
} elseif ($val > 1) {
$gradient['coords'][$key] = 1;
}
}
}
if (($gradient['type'] == 2) AND ($gradient['coords'][0] == $gradient['coords'][2]) AND ($gradient['coords'][1] == $gradient['coords'][3])) {
$gradient['coords'][0] = 1;
$gradient['coords'][1] = 0;
$gradient['coords'][2] = 0.999;
$gradient['coords'][3] = 0;
}
$tmp = $gradient['coords'][1];
$gradient['coords'][1] = $gradient['coords'][3];
$gradient['coords'][3] = $tmp;
$cy = ($this->h - $y);
if ($gradient['type'] == 3) {
$cy -= ($gradient['coords'][1] * ($w + $h));
$h = $w = max($w, $h);
} else {
$cy -= $h;
}
$this->_out(sprintf('%F 0 0 %F %F %F cm', ($w * $this->k), ($h * $this->k), ($x * $this->k), ($cy * $this->k)));
if (count($gradient['stops']) > 1) {
$this->Gradient($gradient['type'], $gradient['coords'], $gradient['stops'], array(), false);
}
} elseif ($svgstyle['fill'] != 'none') {
$fill_color = TCPDF_COLORS::convertHTMLColorToDec($svgstyle['fill'], $this->spot_colors);
if ($svgstyle['fill-opacity'] != 1) {
$this->setAlpha($this->alpha['CA'], 'Normal', $svgstyle['fill-opacity'], false);
}
$this->SetFillColorArray($fill_color);
if ($svgstyle['fill-rule'] == 'evenodd') {
$objstyle .= 'F*';
} else {
$objstyle .= 'F';
}
}
if ($svgstyle['stroke'] != 'none') {
if ($svgstyle['stroke-opacity'] != 1) {
$this->setAlpha($svgstyle['stroke-opacity'], 'Normal', $this->alpha['ca'], false);
} elseif (preg_match('/rgba\(\d+%?,\s*\d+%?,\s*\d+%?,\s*(\d+(?:\.\d+)?)\)/i', $svgstyle['stroke'], $rgba_matches)) {
$this->setAlpha($rgba_matches[1], 'Normal', $this->alpha['ca'], false);
}
$stroke_style = array(
'color' => TCPDF_COLORS::convertHTMLColorToDec($svgstyle['stroke'], $this->spot_colors),
'width' => $this->getHTMLUnitToUnits($svgstyle['stroke-width'], 0, $this->svgunit, false),
'cap' => $svgstyle['stroke-linecap'],
'join' => $svgstyle['stroke-linejoin']
);
if (isset($svgstyle['stroke-dasharray']) AND !empty($svgstyle['stroke-dasharray']) AND ($svgstyle['stroke-dasharray'] != 'none')) {
$stroke_style['dash'] = $svgstyle['stroke-dasharray'];
}
$this->SetLineStyle($stroke_style);
$objstyle .= 'D';
}
$regs = array();
if (!empty($svgstyle['font'])) {
if (preg_match('/font-family[\s]*:[\s]*([^\;\"]*)/si', $svgstyle['font'], $regs)) {
$font_family = $this->getFontFamilyName($regs[1]);
} else {
$font_family = $svgstyle['font-family'];
}
if (preg_match('/font-size[\s]*:[\s]*([^\s\;\"]*)/si', $svgstyle['font'], $regs)) {
$font_size = trim($regs[1]);
} else {
$font_size = $svgstyle['font-size'];
}
if (preg_match('/font-style[\s]*:[\s]*([^\s\;\"]*)/si', $svgstyle['font'], $regs)) {
$font_style = trim($regs[1]);
} else {
$font_style = $svgstyle['font-style'];
}
if (preg_match('/font-weight[\s]*:[\s]*([^\s\;\"]*)/si', $svgstyle['font'], $regs)) {
$font_weight = trim($regs[1]);
} else {
$font_weight = $svgstyle['font-weight'];
}
if (preg_match('/font-stretch[\s]*:[\s]*([^\s\;\"]*)/si', $svgstyle['font'], $regs)) {
$font_stretch = trim($regs[1]);
} else {
$font_stretch = $svgstyle['font-stretch'];
}
if (preg_match('/letter-spacing[\s]*:[\s]*([^\s\;\"]*)/si', $svgstyle['font'], $regs)) {
$font_spacing = trim($regs[1]);
} else {
$font_spacing = $svgstyle['letter-spacing'];
}
} else {
$font_family = $this->getFontFamilyName($svgstyle['font-family']);
$font_size = $svgstyle['font-size'];
$font_style = $svgstyle['font-style'];
$font_weight = $svgstyle['font-weight'];
$font_stretch = $svgstyle['font-stretch'];
$font_spacing = $svgstyle['letter-spacing'];
}
$font_size = $this->getHTMLFontUnits($font_size, $this->svgstyles[0]['font-size'], $prevsvgstyle['font-size'], $this->svgunit);
$font_stretch = $this->getCSSFontStretching($font_stretch, $svgstyle['font-stretch']);
$font_spacing = $this->getCSSFontSpacing($font_spacing, $svgstyle['letter-spacing']);
switch ($font_style) {
case 'italic': {
$font_style = 'I';
break;
}
case 'oblique': {
$font_style = 'I';
break;
}
default:
case 'normal': {
$font_style = '';
break;
}
}
switch ($font_weight) {
case 'bold':
case 'bolder': {
$font_style .= 'B';
break;
}
case 'normal': {
if ((substr($font_family, -1) == 'I') AND (substr($font_family, -2, 1) == 'B')) {
$font_family = substr($font_family, 0, -2).'I';
} elseif (substr($font_family, -1) == 'B') {
$font_family = substr($font_family, 0, -1);
}
break;
}
}
switch ($svgstyle['text-decoration']) {
case 'underline': {
$font_style .= 'U';
break;
}
case 'overline': {
$font_style .= 'O';
break;
}
case 'line-through': {
$font_style .= 'D';
break;
}
default:
case 'none': {
break;
}
}
$this->SetFont($font_family, $font_style, $font_size);
$this->setFontStretching($font_stretch);
$this->setFontSpacing($font_spacing);
return $objstyle;
}
protected function SVGPath($d, $style='') {
if ($this->state != 2) {
return;
}
$op = TCPDF_STATIC::getPathPaintOperator($style, '');
if (empty($op)) {
return;
}
$paths = array();
$d = preg_replace('/([0-9ACHLMQSTVZ])([\-\+])/si', '\\1 \\2', $d);
preg_match_all('/([ACHLMQSTVZ])[\s]*([^ACHLMQSTVZ\"]*)/si', $d, $paths, PREG_SET_ORDER);
$x = 0;
$y = 0;
$x1 = 0;
$y1 = 0;
$x2 = 0;
$y2 = 0;
$xmin = 2147483647;
$xmax = 0;
$ymin = 2147483647;
$ymax = 0;
$relcoord = false;
$minlen = (0.01 / $this->k);
$firstcmd = true;
foreach ($paths as $key => $val) {
$cmd = trim($val[1]);
if (strtolower($cmd) == $cmd) {
$relcoord = true;
$xoffset = $x;
$yoffset = $y;
} else {
$relcoord = false;
$xoffset = 0;
$yoffset = 0;
}
$params = array();
if (isset($val[2])) {
$rawparams = preg_split('/([\,\s]+)/si', trim($val[2]));
$params = array();
foreach ($rawparams as $ck => $cp) {
$params[$ck] = $this->getHTMLUnitToUnits($cp, 0, $this->svgunit, false);
if (abs($params[$ck]) < $minlen) {
$params[$ck] = 0;
}
}
}
$x0 = $x;
$y0 = $y;
switch (strtoupper($cmd)) {
case 'M': {
foreach ($params as $ck => $cp) {
if (($ck % 2) == 0) {
$x = $cp + $xoffset;
} else {
$y = $cp + $yoffset;
if ($firstcmd OR (abs($x0 - $x) >= $minlen) OR (abs($y0 - $y) >= $minlen)) {
if ($ck == 1) {
$this->_outPoint($x, $y);
$firstcmd = false;
} else {
$this->_outLine($x, $y);
}
$x0 = $x;
$y0 = $y;
}
$xmin = min($xmin, $x);
$ymin = min($ymin, $y);
$xmax = max($xmax, $x);
$ymax = max($ymax, $y);
if ($relcoord) {
$xoffset = $x;
$yoffset = $y;
}
}
}
break;
}
case 'L': {
foreach ($params as $ck => $cp) {
if (($ck % 2) == 0) {
$x = $cp + $xoffset;
} else {
$y = $cp + $yoffset;
if ((abs($x0 - $x) >= $minlen) OR (abs($y0 - $y) >= $minlen)) {
$this->_outLine($x, $y);
$x0 = $x;
$y0 = $y;
}
$xmin = min($xmin, $x);
$ymin = min($ymin, $y);
$xmax = max($xmax, $x);
$ymax = max($ymax, $y);
if ($relcoord) {
$xoffset = $x;
$yoffset = $y;
}
}
}
break;
}
case 'H': {
foreach ($params as $ck => $cp) {
$x = $cp + $xoffset;
if ((abs($x0 - $x) >= $minlen) OR (abs($y0 - $y) >= $minlen)) {
$this->_outLine($x, $y);
$x0 = $x;
$y0 = $y;
}
$xmin = min($xmin, $x);
$xmax = max($xmax, $x);
if ($relcoord) {
$xoffset = $x;
}
}
break;
}
case 'V': {
foreach ($params as $ck => $cp) {
$y = $cp + $yoffset;
if ((abs($x0 - $x) >= $minlen) OR (abs($y0 - $y) >= $minlen)) {
$this->_outLine($x, $y);
$x0 = $x;
$y0 = $y;
}
$ymin = min($ymin, $y);
$ymax = max($ymax, $y);
if ($relcoord) {
$yoffset = $y;
}
}
break;
}
case 'C': {
foreach ($params as $ck => $cp) {
$params[$ck] = $cp;
if ((($ck + 1) % 6) == 0) {
$x1 = $params[($ck - 5)] + $xoffset;
$y1 = $params[($ck - 4)] + $yoffset;
$x2 = $params[($ck - 3)] + $xoffset;
$y2 = $params[($ck - 2)] + $yoffset;
$x = $params[($ck - 1)] + $xoffset;
$y = $params[($ck)] + $yoffset;
$this->_outCurve($x1, $y1, $x2, $y2, $x, $y);
$xmin = min($xmin, $x, $x1, $x2);
$ymin = min($ymin, $y, $y1, $y2);
$xmax = max($xmax, $x, $x1, $x2);
$ymax = max($ymax, $y, $y1, $y2);
if ($relcoord) {
$xoffset = $x;
$yoffset = $y;
}
}
}
break;
}
case 'S': {
foreach ($params as $ck => $cp) {
$params[$ck] = $cp;
if ((($ck + 1) % 4) == 0) {
if (($key > 0) AND ((strtoupper($paths[($key - 1)][1]) == 'C') OR (strtoupper($paths[($key - 1)][1]) == 'S'))) {
$x1 = (2 * $x) - $x2;
$y1 = (2 * $y) - $y2;
} else {
$x1 = $x;
$y1 = $y;
}
$x2 = $params[($ck - 3)] + $xoffset;
$y2 = $params[($ck - 2)] + $yoffset;
$x = $params[($ck - 1)] + $xoffset;
$y = $params[($ck)] + $yoffset;
$this->_outCurve($x1, $y1, $x2, $y2, $x, $y);
$xmin = min($xmin, $x, $x1, $x2);
$ymin = min($ymin, $y, $y1, $y2);
$xmax = max($xmax, $x, $x1, $x2);
$ymax = max($ymax, $y, $y1, $y2);
if ($relcoord) {
$xoffset = $x;
$yoffset = $y;
}
}
}
break;
}
case 'Q': {
foreach ($params as $ck => $cp) {
$params[$ck] = $cp;
if ((($ck + 1) % 4) == 0) {
$x1 = $params[($ck - 3)] + $xoffset;
$y1 = $params[($ck - 2)] + $yoffset;
$xa = ($x + (2 * $x1)) / 3;
$ya = ($y + (2 * $y1)) / 3;
$x = $params[($ck - 1)] + $xoffset;
$y = $params[($ck)] + $yoffset;
$xb = ($x + (2 * $x1)) / 3;
$yb = ($y + (2 * $y1)) / 3;
$this->_outCurve($xa, $ya, $xb, $yb, $x, $y);
$xmin = min($xmin, $x, $xa, $xb);
$ymin = min($ymin, $y, $ya, $yb);
$xmax = max($xmax, $x, $xa, $xb);
$ymax = max($ymax, $y, $ya, $yb);
if ($relcoord) {
$xoffset = $x;
$yoffset = $y;
}
}
}
break;
}
case 'T': {
foreach ($params as $ck => $cp) {
$params[$ck] = $cp;
if (($ck % 2) != 0) {
if (($key > 0) AND ((strtoupper($paths[($key - 1)][1]) == 'Q') OR (strtoupper($paths[($key - 1)][1]) == 'T'))) {
$x1 = (2 * $x) - $x1;
$y1 = (2 * $y) - $y1;
} else {
$x1 = $x;
$y1 = $y;
}
$xa = ($x + (2 * $x1)) / 3;
$ya = ($y + (2 * $y1)) / 3;
$x = $params[($ck - 1)] + $xoffset;
$y = $params[($ck)] + $yoffset;
$xb = ($x + (2 * $x1)) / 3;
$yb = ($y + (2 * $y1)) / 3;
$this->_outCurve($xa, $ya, $xb, $yb, $x, $y);
$xmin = min($xmin, $x, $xa, $xb);
$ymin = min($ymin, $y, $ya, $yb);
$xmax = max($xmax, $x, $xa, $xb);
$ymax = max($ymax, $y, $ya, $yb);
if ($relcoord) {
$xoffset = $x;
$yoffset = $y;
}
}
}
break;
}
case 'A': {
foreach ($params as $ck => $cp) {
$params[$ck] = $cp;
if ((($ck + 1) % 7) == 0) {
$x0 = $x;
$y0 = $y;
$rx = abs($params[($ck - 6)]);
$ry = abs($params[($ck - 5)]);
$ang = -$rawparams[($ck - 4)];
$angle = deg2rad($ang);
$fa = $rawparams[($ck - 3)];
$fs = $rawparams[($ck - 2)];
$x = $params[($ck - 1)] + $xoffset;
$y = $params[$ck] + $yoffset;
if ((abs($x0 - $x) < $minlen) AND (abs($y0 - $y) < $minlen)) {
$xmin = min($xmin, $x);
$ymin = min($ymin, $y);
$xmax = max($xmax, $x);
$ymax = max($ymax, $y);
} else {
$cos_ang = cos($angle);
$sin_ang = sin($angle);
$a = (($x0 - $x) / 2);
$b = (($y0 - $y) / 2);
$xa = ($a * $cos_ang) - ($b * $sin_ang);
$ya = ($a * $sin_ang) + ($b * $cos_ang);
$rx2 = $rx * $rx;
$ry2 = $ry * $ry;
$xa2 = $xa * $xa;
$ya2 = $ya * $ya;
$delta = ($xa2 / $rx2) + ($ya2 / $ry2);
if ($delta > 1) {
$rx *= sqrt($delta);
$ry *= sqrt($delta);
$rx2 = $rx * $rx;
$ry2 = $ry * $ry;
}
$numerator = (($rx2 * $ry2) - ($rx2 * $ya2) - ($ry2 * $xa2));
if ($numerator < 0) {
$root = 0;
} else {
$root = sqrt($numerator / (($rx2 * $ya2) + ($ry2 * $xa2)));
}
if ($fa == $fs){
$root *= -1;
}
$cax = $root * (($rx * $ya) / $ry);
$cay = -$root * (($ry * $xa) / $rx);
$cx = ($cax * $cos_ang) - ($cay * $sin_ang) + (($x0 + $x) / 2);
$cy = ($cax * $sin_ang) + ($cay * $cos_ang) + (($y0 + $y) / 2);
$angs = TCPDF_STATIC::getVectorsAngle(1, 0, (($xa - $cax) / $rx), (($cay - $ya) / $ry));
$dang = TCPDF_STATIC::getVectorsAngle((($xa - $cax) / $rx), (($ya - $cay) / $ry), ((-$xa - $cax) / $rx), ((-$ya - $cay) / $ry));
if (($fs == 0) AND ($dang > 0)) {
$dang -= (2 * M_PI);
} elseif (($fs == 1) AND ($dang < 0)) {
$dang += (2 * M_PI);
}
$angf = $angs - $dang;
if ((($fs == 0) AND ($angs > $angf)) OR (($fs == 1) AND ($angs < $angf))) {
$tmp = $angs;
$angs = $angf;
$angf = $tmp;
}
$angs = round(rad2deg($angs), 6);
$angf = round(rad2deg($angf), 6);
if (($angs < 0) AND ($angf < 0)) {
$angs += 360;
$angf += 360;
}
$pie = false;
if (($key == 0) AND (isset($paths[($key + 1)][1])) AND (trim($paths[($key + 1)][1]) == 'z')) {
$pie = true;
}
list($axmin, $aymin, $axmax, $aymax) = $this->_outellipticalarc($cx, $cy, $rx, $ry, $ang, $angs, $angf, $pie, 2, false, ($fs == 0), true);
$xmin = min($xmin, $x, $axmin);
$ymin = min($ymin, $y, $aymin);
$xmax = max($xmax, $x, $axmax);
$ymax = max($ymax, $y, $aymax);
}
if ($relcoord) {
$xoffset = $x;
$yoffset = $y;
}
}
}
break;
}
case 'Z': {
$this->_out('h');
break;
}
}
$firstcmd = false;
}
if (!empty($op)) {
$this->_out($op);
}
return array($xmin, $ymin, ($xmax - $xmin), ($ymax - $ymin));
}
protected function removeTagNamespace($name) {
if(strpos($name, ':') !== false) {
$parts = explode(':', $name);
return $parts[(sizeof($parts) - 1)];
}
return $name;
}
protected function startSVGElementHandler($parser, $name, $attribs, $ctm=array()) {
$name = $this->removeTagNamespace($name);
if ($this->svgclipmode) {
$this->svgclippaths[$this->svgclipid][] = array('name' => $name, 'attribs' => $attribs, 'tm' => $this->svgcliptm[$this->svgclipid]);
return;
}
if ($this->svgdefsmode AND !in_array($name, array('clipPath', 'linearGradient', 'radialGradient', 'stop'))) {
if (isset($attribs['id'])) {
$attribs['child_elements'] = array();
$this->svgdefs[$attribs['id']] = array('name' => $name, 'attribs' => $attribs);
return;
}
if (end($this->svgdefs) !== FALSE) {
$last_svgdefs_id = key($this->svgdefs);
if (isset($this->svgdefs[$last_svgdefs_id]['attribs']['child_elements'])) {
$attribs['id'] = 'DF_'.(count($this->svgdefs[$last_svgdefs_id]['attribs']['child_elements']) + 1);
$this->svgdefs[$last_svgdefs_id]['attribs']['child_elements'][$attribs['id']] = array('name' => $name, 'attribs' => $attribs);
return;
}
}
return;
}
$clipping = false;
if ($parser == 'clip-path') {
$clipping = true;
}
$prev_svgstyle = $this->svgstyles[max(0,(count($this->svgstyles) - 1))];
$svgstyle = $this->svgstyles[0];
if ($clipping AND !isset($attribs['fill']) AND (!isset($attribs['style']) OR (!preg_match('/[;\"\s]{1}fill[\s]*:[\s]*([^;\"]*)/si', $attribs['style'], $attrval)))) {
$attribs['fill'] = 'none';
}
if (isset($attribs['style']) AND !TCPDF_STATIC::empty_string($attribs['style']) AND ($attribs['style'][0] != ';')) {
$attribs['style'] = ';'.$attribs['style'];
}
foreach ($prev_svgstyle as $key => $val) {
if (in_array($key, TCPDF_IMAGES::$svginheritprop)) {
$svgstyle[$key] = $val;
}
if (isset($attribs[$key]) AND !TCPDF_STATIC::empty_string($attribs[$key])) {
if ($attribs[$key] == 'inherit') {
$svgstyle[$key] = $val;
} else {
$svgstyle[$key] = $attribs[$key];
}
} elseif (isset($attribs['style']) AND !TCPDF_STATIC::empty_string($attribs['style'])) {
$attrval = array();
if (preg_match('/[;\"\s]{1}'.$key.'[\s]*:[\s]*([^;\"]*)/si', $attribs['style'], $attrval) AND isset($attrval[1])) {
if ($attrval[1] == 'inherit') {
$svgstyle[$key] = $val;
} else {
$svgstyle[$key] = $attrval[1];
}
}
}
}
if (!empty($ctm)) {
$tm = $ctm;
} else {
$tm = array(1,0,0,1,0,0);
}
if (isset($attribs['transform']) AND !empty($attribs['transform'])) {
$tm = TCPDF_STATIC::getTransformationMatrixProduct($tm, TCPDF_STATIC::getSVGTransformMatrix($attribs['transform']));
}
$svgstyle['transfmatrix'] = $tm;
$invisible = false;
if (($svgstyle['visibility'] == 'hidden') OR ($svgstyle['visibility'] == 'collapse') OR ($svgstyle['display'] == 'none')) {
$invisible = true;
}
switch($name) {
case 'defs': {
$this->svgdefsmode = true;
break;
}
case 'clipPath': {
if ($invisible) {
break;
}
$this->svgclipmode = true;
if (!isset($attribs['id'])) {
$attribs['id'] = 'CP_'.(count($this->svgcliptm) + 1);
}
$this->svgclipid = $attribs['id'];
$this->svgclippaths[$this->svgclipid] = array();
$this->svgcliptm[$this->svgclipid] = $tm;
break;
}
case 'svg': {
if(++$this->svg_tag_depth <= 1) {
break;
}
array_push($this->svgstyles, $svgstyle);
$this->StartTransform();
$svgX = (isset($attribs['x'])?$attribs['x']:0);
$svgY = (isset($attribs['y'])?$attribs['y']:0);
$svgW = (isset($attribs['width'])?$attribs['width']:0);
$svgH = (isset($attribs['height'])?$attribs['height']:0);
$tm = TCPDF_STATIC::getTransformationMatrixProduct($tm, array( 1, 0, 0, 1, $svgX, $svgY));
$this->SVGTransform($tm);
$x = 0;
$y = 0;
$w = (isset($attribs['width'])?$this->getHTMLUnitToUnits($attribs['width'], 0, $this->svgunit, false):$this->w);
$h = (isset($attribs['height'])?$this->getHTMLUnitToUnits($attribs['height'], 0, $this->svgunit, false):$this->h);
$this->Rect($x, $y, $w, $h, 'CNZ', array(), array());
if (isset($attribs['viewBox'])) {
$tmp = array();
preg_match_all("/[0-9]+/", $attribs['viewBox'], $tmp);
$tmp = $tmp[0];
if (sizeof($tmp) == 4) {
$vx = $tmp[0];
$vy = $tmp[1];
$vw = $tmp[2];
$vh = $tmp[3];
$tmp = array();
$aspectX = 'xMid';
$aspectY = 'YMid';
$fit = 'meet';
if (isset($attribs['preserveAspectRatio'])) {
if($attribs['preserveAspectRatio'] == 'none') {
$fit = 'none';
} else {
preg_match_all('/[a-zA-Z]+/', $attribs['preserveAspectRatio'], $tmp);
$tmp = $tmp[0];
if ((sizeof($tmp) == 2) AND (strlen($tmp[0]) == 8) AND (in_array($tmp[1], array('meet', 'slice', 'none')))) {
$aspectX = substr($tmp[0], 0, 4);
$aspectY = substr($tmp[0], 4, 4);
$fit = $tmp[1];
}
}
}
$wr = ($svgW / $vw);
$hr = ($svgH / $vh);
$ax = $ay = 0;
if ((($fit == 'meet') AND ($hr < $wr)) OR (($fit == 'slice') AND ($hr > $wr))) {
if ($aspectX == 'xMax') {
$ax = (($vw * ($wr / $hr)) - $vw);
}
if ($aspectX == 'xMid') {
$ax = ((($vw * ($wr / $hr)) - $vw) / 2);
}
$wr = $hr;
} elseif ((($fit == 'meet') AND ($hr > $wr)) OR (($fit == 'slice') AND ($hr < $wr))) {
if ($aspectY == 'YMax') {
$ay = (($vh * ($hr / $wr)) - $vh);
}
if ($aspectY == 'YMid') {
$ay = ((($vh * ($hr / $wr)) - $vh) / 2);
}
$hr = $wr;
}
$newtm = array($wr, 0, 0, $hr, (($wr * ($ax - $vx)) - $svgX), (($hr * ($ay - $vy)) - $svgY));
$tm = TCPDF_STATIC::getTransformationMatrixProduct($tm, $newtm);
$this->SVGTransform($tm);
}
}
$this->setSVGStyles($svgstyle, $prev_svgstyle);
break;
}
case 'g': {
array_push($this->svgstyles, $svgstyle);
$this->StartTransform();
$x = (isset($attribs['x'])?$attribs['x']:0);
$y = (isset($attribs['y'])?$attribs['y']:0);
$w = 1;
$h = 1;
$tm = TCPDF_STATIC::getTransformationMatrixProduct($tm, array($w, 0, 0, $h, $x, $y));
$this->SVGTransform($tm);
$this->setSVGStyles($svgstyle, $prev_svgstyle);
break;
}
case 'linearGradient': {
if ($this->pdfa_mode) {
break;
}
if (!isset($attribs['id'])) {
$attribs['id'] = 'GR_'.(count($this->svggradients) + 1);
}
$this->svggradientid = $attribs['id'];
$this->svggradients[$this->svggradientid] = array();
$this->svggradients[$this->svggradientid]['type'] = 2;
$this->svggradients[$this->svggradientid]['stops'] = array();
if (isset($attribs['gradientUnits'])) {
$this->svggradients[$this->svggradientid]['gradientUnits'] = $attribs['gradientUnits'];
} else {
$this->svggradients[$this->svggradientid]['gradientUnits'] = 'objectBoundingBox';
}
if (((!isset($attribs['x1'])) AND (!isset($attribs['y1'])) AND (!isset($attribs['x2'])) AND (!isset($attribs['y2'])))
OR ((isset($attribs['x1']) AND (substr($attribs['x1'], -1) == '%'))
OR (isset($attribs['y1']) AND (substr($attribs['y1'], -1) == '%'))
OR (isset($attribs['x2']) AND (substr($attribs['x2'], -1) == '%'))
OR (isset($attribs['y2']) AND (substr($attribs['y2'], -1) == '%')))) {
$this->svggradients[$this->svggradientid]['mode'] = 'percentage';
} else {
$this->svggradients[$this->svggradientid]['mode'] = 'measure';
}
$x1 = (isset($attribs['x1'])?$attribs['x1']:'0');
$y1 = (isset($attribs['y1'])?$attribs['y1']:'0');
$x2 = (isset($attribs['x2'])?$attribs['x2']:'100');
$y2 = (isset($attribs['y2'])?$attribs['y2']:'0');
if (isset($attribs['gradientTransform'])) {
$this->svggradients[$this->svggradientid]['gradientTransform'] = TCPDF_STATIC::getSVGTransformMatrix($attribs['gradientTransform']);
}
$this->svggradients[$this->svggradientid]['coords'] = array($x1, $y1, $x2, $y2);
if (isset($attribs['xlink:href']) AND !empty($attribs['xlink:href'])) {
$this->svggradients[$this->svggradientid]['xref'] = substr($attribs['xlink:href'], 1);
}
break;
}
case 'radialGradient': {
if ($this->pdfa_mode) {
break;
}
if (!isset($attribs['id'])) {
$attribs['id'] = 'GR_'.(count($this->svggradients) + 1);
}
$this->svggradientid = $attribs['id'];
$this->svggradients[$this->svggradientid] = array();
$this->svggradients[$this->svggradientid]['type'] = 3;
$this->svggradients[$this->svggradientid]['stops'] = array();
if (isset($attribs['gradientUnits'])) {
$this->svggradients[$this->svggradientid]['gradientUnits'] = $attribs['gradientUnits'];
} else {
$this->svggradients[$this->svggradientid]['gradientUnits'] = 'objectBoundingBox';
}
if (((!isset($attribs['cx'])) AND (!isset($attribs['cy'])))
OR ((isset($attribs['cx']) AND (substr($attribs['cx'], -1) == '%'))
OR (isset($attribs['cy']) AND (substr($attribs['cy'], -1) == '%')))) {
$this->svggradients[$this->svggradientid]['mode'] = 'percentage';
} elseif (isset($attribs['r']) AND is_numeric($attribs['r']) AND ($attribs['r']) <= 1) {
$this->svggradients[$this->svggradientid]['mode'] = 'ratio';
} else {
$this->svggradients[$this->svggradientid]['mode'] = 'measure';
}
$cx = (isset($attribs['cx']) ? $attribs['cx'] : 0.5);
$cy = (isset($attribs['cy']) ? $attribs['cy'] : 0.5);
$fx = (isset($attribs['fx']) ? $attribs['fx'] : $cx);
$fy = (isset($attribs['fy']) ? $attribs['fy'] : $cy);
$r = (isset($attribs['r']) ? $attribs['r'] : 0.5);
if (isset($attribs['gradientTransform'])) {
$this->svggradients[$this->svggradientid]['gradientTransform'] = TCPDF_STATIC::getSVGTransformMatrix($attribs['gradientTransform']);
}
$this->svggradients[$this->svggradientid]['coords'] = array($cx, $cy, $fx, $fy, $r);
if (isset($attribs['xlink:href']) AND !empty($attribs['xlink:href'])) {
$this->svggradients[$this->svggradientid]['xref'] = substr($attribs['xlink:href'], 1);
}
break;
}
case 'stop': {
if (substr($attribs['offset'], -1) == '%') {
$offset = floatval(substr($attribs['offset'], -1)) / 100;
} else {
$offset = floatval($attribs['offset']);
if ($offset > 1) {
$offset /= 100;
}
}
$stop_color = isset($svgstyle['stop-color'])?TCPDF_COLORS::convertHTMLColorToDec($svgstyle['stop-color'], $this->spot_colors):'black';
$opacity = isset($svgstyle['stop-opacity'])?$svgstyle['stop-opacity']:1;
$this->svggradients[$this->svggradientid]['stops'][] = array('offset' => $offset, 'color' => $stop_color, 'opacity' => $opacity);
break;
}
case 'path': {
if ($invisible) {
break;
}
if (isset($attribs['d'])) {
$d = trim($attribs['d']);
if (!empty($d)) {
$x = (isset($attribs['x'])?$attribs['x']:0);
$y = (isset($attribs['y'])?$attribs['y']:0);
$w = (isset($attribs['width'])?$attribs['width']:1);
$h = (isset($attribs['height'])?$attribs['height']:1);
$tm = TCPDF_STATIC::getTransformationMatrixProduct($tm, array($w, 0, 0, $h, $x, $y));
if ($clipping) {
$this->SVGTransform($tm);
$this->SVGPath($d, 'CNZ');
} else {
$this->StartTransform();
$this->SVGTransform($tm);
$obstyle = $this->setSVGStyles($svgstyle, $prev_svgstyle, $x, $y, $w, $h, 'SVGPath', array($d, 'CNZ'));
if (!empty($obstyle)) {
$this->SVGPath($d, $obstyle);
}
$this->StopTransform();
}
}
}
break;
}
case 'rect': {
if ($invisible) {
break;
}
$x = (isset($attribs['x'])?$this->getHTMLUnitToUnits($attribs['x'], 0, $this->svgunit, false):0);
$y = (isset($attribs['y'])?$this->getHTMLUnitToUnits($attribs['y'], 0, $this->svgunit, false):0);
$w = (isset($attribs['width'])?$this->getHTMLUnitToUnits($attribs['width'], 0, $this->svgunit, false):0);
$h = (isset($attribs['height'])?$this->getHTMLUnitToUnits($attribs['height'], 0, $this->svgunit, false):0);
$rx = (isset($attribs['rx'])?$this->getHTMLUnitToUnits($attribs['rx'], 0, $this->svgunit, false):0);
$ry = (isset($attribs['ry'])?$this->getHTMLUnitToUnits($attribs['ry'], 0, $this->svgunit, false):$rx);
if ($clipping) {
$this->SVGTransform($tm);
$this->RoundedRectXY($x, $y, $w, $h, $rx, $ry, '1111', 'CNZ', array(), array());
} else {
$this->StartTransform();
$this->SVGTransform($tm);
$obstyle = $this->setSVGStyles($svgstyle, $prev_svgstyle, $x, $y, $w, $h, 'RoundedRectXY', array($x, $y, $w, $h, $rx, $ry, '1111', 'CNZ'));
if (!empty($obstyle)) {
$this->RoundedRectXY($x, $y, $w, $h, $rx, $ry, '1111', $obstyle, array(), array());
}
$this->StopTransform();
}
break;
}
case 'circle': {
if ($invisible) {
break;
}
$r = (isset($attribs['r']) ? $this->getHTMLUnitToUnits($attribs['r'], 0, $this->svgunit, false) : 0);
$cx = (isset($attribs['cx']) ? $this->getHTMLUnitToUnits($attribs['cx'], 0, $this->svgunit, false) : (isset($attribs['x']) ? $this->getHTMLUnitToUnits($attribs['x'], 0, $this->svgunit, false) : 0));
$cy = (isset($attribs['cy']) ? $this->getHTMLUnitToUnits($attribs['cy'], 0, $this->svgunit, false) : (isset($attribs['y']) ? $this->getHTMLUnitToUnits($attribs['y'], 0, $this->svgunit, false) : 0));
$x = ($cx - $r);
$y = ($cy - $r);
$w = (2 * $r);
$h = $w;
if ($clipping) {
$this->SVGTransform($tm);
$this->Circle($cx, $cy, $r, 0, 360, 'CNZ', array(), array(), 8);
} else {
$this->StartTransform();
$this->SVGTransform($tm);
$obstyle = $this->setSVGStyles($svgstyle, $prev_svgstyle, $x, $y, $w, $h, 'Circle', array($cx, $cy, $r, 0, 360, 'CNZ'));
if (!empty($obstyle)) {
$this->Circle($cx, $cy, $r, 0, 360, $obstyle, array(), array(), 8);
}
$this->StopTransform();
}
break;
}
case 'ellipse': {
if ($invisible) {
break;
}
$rx = (isset($attribs['rx']) ? $this->getHTMLUnitToUnits($attribs['rx'], 0, $this->svgunit, false) : 0);
$ry = (isset($attribs['ry']) ? $this->getHTMLUnitToUnits($attribs['ry'], 0, $this->svgunit, false) : 0);
$cx = (isset($attribs['cx']) ? $this->getHTMLUnitToUnits($attribs['cx'], 0, $this->svgunit, false) : (isset($attribs['x']) ? $this->getHTMLUnitToUnits($attribs['x'], 0, $this->svgunit, false) : 0));
$cy = (isset($attribs['cy']) ? $this->getHTMLUnitToUnits($attribs['cy'], 0, $this->svgunit, false) : (isset($attribs['y']) ? $this->getHTMLUnitToUnits($attribs['y'], 0, $this->svgunit, false) : 0));
$x = ($cx - $rx);
$y = ($cy - $ry);
$w = (2 * $rx);
$h = (2 * $ry);
if ($clipping) {
$this->SVGTransform($tm);
$this->Ellipse($cx, $cy, $rx, $ry, 0, 0, 360, 'CNZ', array(), array(), 8);
} else {
$this->StartTransform();
$this->SVGTransform($tm);
$obstyle = $this->setSVGStyles($svgstyle, $prev_svgstyle, $x, $y, $w, $h, 'Ellipse', array($cx, $cy, $rx, $ry, 0, 0, 360, 'CNZ'));
if (!empty($obstyle)) {
$this->Ellipse($cx, $cy, $rx, $ry, 0, 0, 360, $obstyle, array(), array(), 8);
}
$this->StopTransform();
}
break;
}
case 'line': {
if ($invisible) {
break;
}
$x1 = (isset($attribs['x1'])?$this->getHTMLUnitToUnits($attribs['x1'], 0, $this->svgunit, false):0);
$y1 = (isset($attribs['y1'])?$this->getHTMLUnitToUnits($attribs['y1'], 0, $this->svgunit, false):0);
$x2 = (isset($attribs['x2'])?$this->getHTMLUnitToUnits($attribs['x2'], 0, $this->svgunit, false):0);
$y2 = (isset($attribs['y2'])?$this->getHTMLUnitToUnits($attribs['y2'], 0, $this->svgunit, false):0);
$x = $x1;
$y = $y1;
$w = abs($x2 - $x1);
$h = abs($y2 - $y1);
if (!$clipping) {
$this->StartTransform();
$this->SVGTransform($tm);
$obstyle = $this->setSVGStyles($svgstyle, $prev_svgstyle, $x, $y, $w, $h, 'Line', array($x1, $y1, $x2, $y2));
$this->Line($x1, $y1, $x2, $y2);
$this->StopTransform();
}
break;
}
case 'polyline':
case 'polygon': {
if ($invisible) {
break;
}
$points = (isset($attribs['points'])?$attribs['points']:'0 0');
$points = trim($points);
$points = preg_split('/[\,\s]+/si', $points);
if (count($points) < 4) {
break;
}
$p = array();
$xmin = 2147483647;
$xmax = 0;
$ymin = 2147483647;
$ymax = 0;
foreach ($points as $key => $val) {
$p[$key] = $this->getHTMLUnitToUnits($val, 0, $this->svgunit, false);
if (($key % 2) == 0) {
$xmin = min($xmin, $p[$key]);
$xmax = max($xmax, $p[$key]);
} else {
$ymin = min($ymin, $p[$key]);
$ymax = max($ymax, $p[$key]);
}
}
$x = $xmin;
$y = $ymin;
$w = ($xmax - $xmin);
$h = ($ymax - $ymin);
if ($name == 'polyline') {
$this->StartTransform();
$this->SVGTransform($tm);
$obstyle = $this->setSVGStyles($svgstyle, $prev_svgstyle, $x, $y, $w, $h, 'PolyLine', array($p, 'CNZ'));
if (!empty($obstyle)) {
$this->PolyLine($p, $obstyle, array(), array());
}
$this->StopTransform();
} else {
if ($clipping) {
$this->SVGTransform($tm);
$this->Polygon($p, 'CNZ', array(), array(), true);
} else {
$this->StartTransform();
$this->SVGTransform($tm);
$obstyle = $this->setSVGStyles($svgstyle, $prev_svgstyle, $x, $y, $w, $h, 'Polygon', array($p, 'CNZ'));
if (!empty($obstyle)) {
$this->Polygon($p, $obstyle, array(), array(), true);
}
$this->StopTransform();
}
}
break;
}
case 'image': {
if ($invisible) {
break;
}
if (!isset($attribs['xlink:href']) OR empty($attribs['xlink:href'])) {
break;
}
$x = (isset($attribs['x'])?$this->getHTMLUnitToUnits($attribs['x'], 0, $this->svgunit, false):0);
$y = (isset($attribs['y'])?$this->getHTMLUnitToUnits($attribs['y'], 0, $this->svgunit, false):0);
$w = (isset($attribs['width'])?$this->getHTMLUnitToUnits($attribs['width'], 0, $this->svgunit, false):0);
$h = (isset($attribs['height'])?$this->getHTMLUnitToUnits($attribs['height'], 0, $this->svgunit, false):0);
$img = $attribs['xlink:href'];
if (!$clipping) {
$this->StartTransform();
$this->SVGTransform($tm);
$obstyle = $this->setSVGStyles($svgstyle, $prev_svgstyle, $x, $y, $w, $h);
if (preg_match('/^data:image\/[^;]+;base64,/', $img, $m) > 0) {
$img = '@'.base64_decode(substr($img, strlen($m[0])));
} else {
if (!TCPDF_STATIC::empty_string($this->svgdir) AND (($img[0] == '.') OR (basename($img) == $img))) {
$img = $this->svgdir.'/'.$img;
}
if (($img[0] == '/') AND !empty($_SERVER['DOCUMENT_ROOT']) AND ($_SERVER['DOCUMENT_ROOT'] != '/')) {
$findroot = strpos($img, $_SERVER['DOCUMENT_ROOT']);
if (($findroot === false) OR ($findroot > 1)) {
if (substr($_SERVER['DOCUMENT_ROOT'], -1) == '/') {
$img = substr($_SERVER['DOCUMENT_ROOT'], 0, -1).$img;
} else {
$img = $_SERVER['DOCUMENT_ROOT'].$img;
}
}
}
$img = urldecode($img);
$testscrtype = @parse_url($img);
if (!isset($testscrtype['query']) OR empty($testscrtype['query'])) {
$img = str_replace(K_PATH_URL, K_PATH_MAIN, $img);
}
}
$imgtype = TCPDF_IMAGES::getImageFileType($img);
if (($imgtype == 'eps') OR ($imgtype == 'ai')) {
$this->ImageEps($img, $x, $y, $w, $h);
} elseif ($imgtype == 'svg') {
$svggradients = $this->svggradients;
$svggradientid = $this->svggradientid;
$svgdefsmode = $this->svgdefsmode;
$svgdefs = $this->svgdefs;
$svgclipmode = $this->svgclipmode;
$svgclippaths = $this->svgclippaths;
$svgcliptm = $this->svgcliptm;
$svgclipid = $this->svgclipid;
$svgtext = $this->svgtext;
$svgtextmode = $this->svgtextmode;
$this->ImageSVG($img, $x, $y, $w, $h);
$this->svggradients = $svggradients;
$this->svggradientid = $svggradientid;
$this->svgdefsmode = $svgdefsmode;
$this->svgdefs = $svgdefs;
$this->svgclipmode = $svgclipmode;
$this->svgclippaths = $svgclippaths;
$this->svgcliptm = $svgcliptm;
$this->svgclipid = $svgclipid;
$this->svgtext = $svgtext;
$this->svgtextmode = $svgtextmode;
} else {
$this->Image($img, $x, $y, $w, $h);
}
$this->StopTransform();
}
break;
}
case 'text':
case 'tspan': {
if (isset($this->svgtextmode['text-anchor']) AND !empty($this->svgtext)) {
}
$this->svgtextmode['invisible'] = $invisible;
if ($invisible) {
break;
}
array_push($this->svgstyles, $svgstyle);
if (isset($attribs['x'])) {
$x = $this->getHTMLUnitToUnits($attribs['x'], 0, $this->svgunit, false);
} elseif ($name == 'tspan') {
$x = $this->x;
} else {
$x = 0;
}
if (isset($attribs['dx'])) {
$x += $this->getHTMLUnitToUnits($attribs['dx'], 0, $this->svgunit, false);
}
if (isset($attribs['y'])) {
$y = $this->getHTMLUnitToUnits($attribs['y'], 0, $this->svgunit, false);
} elseif ($name == 'tspan') {
$y = $this->y;
} else {
$y = 0;
}
if (isset($attribs['dy'])) {
$y += $this->getHTMLUnitToUnits($attribs['dy'], 0, $this->svgunit, false);
}
$svgstyle['text-color'] = $svgstyle['fill'];
$this->svgtext = '';
if (isset($svgstyle['text-anchor'])) {
$this->svgtextmode['text-anchor'] = $svgstyle['text-anchor'];
} else {
$this->svgtextmode['text-anchor'] = 'start';
}
if (isset($svgstyle['direction'])) {
if ($svgstyle['direction'] == 'rtl') {
$this->svgtextmode['rtl'] = true;
} else {
$this->svgtextmode['rtl'] = false;
}
} else {
$this->svgtextmode['rtl'] = false;
}
if (isset($svgstyle['stroke']) AND ($svgstyle['stroke'] != 'none') AND isset($svgstyle['stroke-width']) AND ($svgstyle['stroke-width'] > 0)) {
$this->svgtextmode['stroke'] = $this->getHTMLUnitToUnits($svgstyle['stroke-width'], 0, $this->svgunit, false);
} else {
$this->svgtextmode['stroke'] = false;
}
$this->StartTransform();
$this->SVGTransform($tm);
$obstyle = $this->setSVGStyles($svgstyle, $prev_svgstyle, $x, $y, 1, 1);
$this->x = $x;
$this->y = $y;
break;
}
case 'use': {
if (isset($attribs['xlink:href']) AND !empty($attribs['xlink:href'])) {
$svgdefid = substr($attribs['xlink:href'], 1);
if (isset($this->svgdefs[$svgdefid])) {
$use = $this->svgdefs[$svgdefid];
if (isset($attribs['xlink:href'])) {
unset($attribs['xlink:href']);
}
if (isset($attribs['id'])) {
unset($attribs['id']);
}
if (isset($use['attribs']['x']) AND isset($attribs['x'])) {
$attribs['x'] += $use['attribs']['x'];
}
if (isset($use['attribs']['y']) AND isset($attribs['y'])) {
$attribs['y'] += $use['attribs']['y'];
}
if (empty($attribs['style'])) {
$attribs['style'] = '';
}
if (!empty($use['attribs']['style'])) {
$attribs['style'] = str_replace(';;',';',';'.$use['attribs']['style'].$attribs['style']);
}
$attribs = array_merge($use['attribs'], $attribs);
$this->startSVGElementHandler($parser, $use['name'], $attribs);
return;
}
}
break;
}
default: {
break;
}
}
if (!empty($attribs['child_elements'])) {
$child_elements = $attribs['child_elements'];
unset($attribs['child_elements']);
foreach($child_elements as $child_element) {
if (empty($child_element['attribs']['closing_tag'])) {
$this->startSVGElementHandler('child-tag', $child_element['name'], $child_element['attribs']);
} else {
if (isset($child_element['attribs']['content'])) {
$this->svgtext = $child_element['attribs']['content'];
}
$this->endSVGElementHandler('child-tag', $child_element['name']);
}
}
}
}
protected function endSVGElementHandler($parser, $name) {
$name = $this->removeTagNamespace($name);
if ($this->svgdefsmode AND !in_array($name, array('defs', 'clipPath', 'linearGradient', 'radialGradient', 'stop'))) {;
if (end($this->svgdefs) !== FALSE) {
$last_svgdefs_id = key($this->svgdefs);
if (isset($this->svgdefs[$last_svgdefs_id]['attribs']['child_elements'])) {
foreach($this->svgdefs[$last_svgdefs_id]['attribs']['child_elements'] as $child_element) {
if (isset($child_element['attribs']['id']) AND ($child_element['name'] == $name)) {
$this->svgdefs[$last_svgdefs_id]['attribs']['child_elements'][$child_element['attribs']['id'].'_CLOSE'] = array('name' => $name, 'attribs' => array('closing_tag' => TRUE, 'content' => $this->svgtext));
return;
}
}
if ($this->svgdefs[$last_svgdefs_id]['name'] == $name) {
$this->svgdefs[$last_svgdefs_id]['attribs']['child_elements'][$last_svgdefs_id.'_CLOSE'] = array('name' => $name, 'attribs' => array('closing_tag' => TRUE, 'content' => $this->svgtext));
return;
}
}
}
return;
}
switch($name) {
case 'defs': {
$this->svgdefsmode = false;
break;
}
case 'clipPath': {
$this->svgclipmode = false;
break;
}
case 'svg': {
if (--$this->svg_tag_depth <= 0) {
break;
}
}
case 'g': {
array_pop($this->svgstyles);
$this->StopTransform();
break;
}
case 'text':
case 'tspan': {
if ($this->svgtextmode['invisible']) {
break;
}
$text = $this->svgtext;
$textlen = $this->GetStringWidth($text);
if ($this->svgtextmode['text-anchor'] != 'start') {
if ($this->svgtextmode['text-anchor'] == 'end') {
if ($this->svgtextmode['rtl']) {
$this->x += $textlen;
} else {
$this->x -= $textlen;
}
} elseif ($this->svgtextmode['text-anchor'] == 'middle') {
if ($this->svgtextmode['rtl']) {
$this->x += ($textlen / 2);
} else {
$this->x -= ($textlen / 2);
}
}
}
$textrendermode = $this->textrendermode;
$textstrokewidth = $this->textstrokewidth;
$this->setTextRenderingMode($this->svgtextmode['stroke'], true, false);
if ($name == 'text') {
$tmpx = $this->x;
$tmpy = $this->y;
}
$this->Cell($textlen, 0, $text, 0, 0, '', false, '', 0, false, 'L', 'T');
if ($name == 'text') {
$this->x = $tmpx;
$this->y = $tmpy;
}
$this->textrendermode = $textrendermode;
$this->textstrokewidth = $textstrokewidth;
$this->svgtext = '';
$this->StopTransform();
if (!$this->svgdefsmode) {
array_pop($this->svgstyles);
}
break;
}
default: {
break;
}
}
}
protected function segSVGContentHandler($parser, $data) {
$this->svgtext .= $data;
}
}